Программирование для многопроцессорных систем в стандарте MPI - Шпаковский Г.И., Серикова Н.В.. Программирование для многопроцессорных систем в стандарте MPI -. Организация вычислений в многопроцессорных системах
Скачать 1.61 Mb.
|
i , и в последнем случае уста- навливается в MPI_UNDEFINED MPI_TESTANY с массивом, со- держащим один активный элемент, эквивалентен MPI_TEST MPI_TESTANY (count, array_of_requests, index, flag, status) IN count длина списка (целое) INOUT array_of_requests массив запросов (массив дескрипторов) OUT index индекс дескриптора для завершенной операции (целое) OUT flag true, если одна из операций завершена (логический тип) OUT status статусный объект (статус) int MPI_Testany (int count, MPI_Request *array_of_requests, int *index, int *flag, MPI_Status *status) MPI_TESTANY(COUNT, ARRAY_OF_REQUESTS, INDEX, FLAG, STATUS, IERROR) LOGICAL FLAG 73 INTEGER COUNT, ARRAY_OF_REQUESTS(*), INDEX, STATUS(MPI_STATUS_SIZE), IERROR static bool MPI::Request::Testany (int count, MPI::Request array_of_requests[], int& index, MPI::Status& status) Функция MPI_WAITALL блокирует работу, пока все операции обмена, связанные с активными дескрипторами в списке, не завершат- ся, и возвращает статус всех операций. Оба массива имеют то же са- мое количество элементов. Элемент с номером i в array_of_statuses устанавливается в возвращаемый статус i -й операции. Запросы, соз- данные операцией неблокирующего обмена, удаляются, и соответст- вующие дескрипторы устанавливаются в MPI_REQUEST_NULL Список может содержать нуль или неактивные дескрипторы. Вызов устанавливает статус каждого такого элемента в состояние empty Когда один или более обменов, завершенных обращением к MPI_WAITALL , оказались неудачны, желательно возвратить специ- альную информацию по каждому обмену. Функция MPI_WAITALL возвращает в таком случае код MPI_ERR_IN_STATUS и устанавли- вает в поля ошибки каждого статуса специфический код ошибки. Этот код будет MPI_SUCCESS , если обмен завершен, или другой код, если обмен не состоялся; или он может быть MPI_ERR_PENDING , если код не завершен и не в состоянии отказа. Функция MPI_WAITALL будет возвращать MPI _ SUCCESS , если никакой из запросов не имеет ошибки, или будет возвращать другой код ошибки, если не выполнил- ся по другим причинам (таким как неверный аргумент). В таком слу- чае он не будет корректировать поле ошибки в статусе. MPI_WAITALL ( count, array_of_requests, array_of_statuses) IN count длина списков (целое) INOUT array_of_requests массив запросов (массив дескрипторов) OUT array_of_statuses массив статусных объектов (массив статусов) int MPI_Waitall (int count, MPI_Request *array_of_requests, MPI_Status *array_of_statuses) MPI_WAITALL(COUNT, ARRAY_OF_REQUESTS, ARRAY_OF_STATUSES, IERROR) INTEGER COUNT, ARRAY_OF_REQUESTS(*) INTEGER ARRAY_OF_STATUSES(MPI_STATUS_SIZE,*), IERROR static void MPI::Request::Waitall (int count, MPI::Request array_of_requests[], MPI::Status array_of_statuses[]) 74 Функция MPI_TESTALL возвращает flag=true , если обмены, свя- занные с активными дескрипторами в массиве, завершены. В этом случае каждый статусный элемент, который соответствует активному дескриптору, устанавливается в статус соответствующего обмена; ес- ли запрос был размещен вызовом неблокирующего обмена, то он уда- ляется, и дескриптор устанавливается в MPI_REQUEST_NULL . Ка- ждый статусный элемент, который соответствует нулю или неактив- ному дескриптору, устанавливается в состояние empty . В противном случае возвращается flag=false , никакие запросы не модифицируются, и значения статусных элементов неопределенные. Это локальная опе- рация. MPI_TESTALL (count, array_of_requests, flag, array_of_statuses) IN count длина списка (целое) INOUT array_of_requests массив запросов (массив дескрипторов) OUT flag (логический тип) OUT array_of_statuses массив статусных объектов(массив статусов) int MPI_Testall(int count, MPI_Request *array_of_requests, int *flag, MPI_Status *array_of_statuses) MPI_TESTALL(COUNT, ARRAY_OF_REQUESTS, FLAG, ARRAY_OF_STATUSES, IERROR) LOGICAL FLAG INTEGER COUNT, ARRAY_OF_REQUESTS(*), ARRAY_OF_STATUSES(MPI_STATUS_SIZE,*), IERROR static bool MPI::Request::Testall (int count, MPI::Request array_of_requests[], MPI::Status array_of_statuses[]) Функция MPI_WAITSOME ожидает, пока, по крайней мере, одна операция, связанная с активным дескриптором в списке, не завершит- ся. Возвращает в outcount число запросов из списка array_of_indices , которые завершены. Возвращает в первую outcount ячейку массива array_of_indices индексы этих операций (индекс внутри ar- ray_of_requests ). Возвращает в первую ячейку outcount массива ar- ray_of_status статус этих завершенных операций. Если завершенный запрос был создан вызовом неблокирующего обмена, то он удаляется, и связанный дескриптор устанавливается в MPI_REQUEST_NULL Если список не содержит активных дескрипторов, то вызов закан- чивается немедленно со значением outcount = MPI_UNDEFINED 75 MPI_WAITSOME (incount, array_of_requests, outcount, array_of_indices, array_of_statuses) IN incount длина массива запросов (целое) INOUT array_of_requests массив запросов (массив дескрипторов) OUT outcount число завершенных запросов (целое) OUT array_of_indices массив индексов операций, которые завершены (массив целых) OUT array_of_statuses массив статусных операций для завершенных операций (массив статусов) int MPI_Waitsome (int incount, MPI_Request *array_of_requests, int *outcount, int *array_of_indices, MPI_Status *array_of_statuses) MPI_WAITSOME (INCOUNT, ARRAY_OF_REQUESTS, OUTCOUNT, ARRAY_OF_INDICES, ARRAY_OF_STATUSES, IERROR) INTEGER INCOUNT, ARRAY_OF_REQUESTS(*), OUTCOUNT, ARRAY_OF_INDICES(*), ARRAY_OF_STATUSES(MPI_STATUS_SIZE,*), IERROR static int MPI::Request::Waitsome(int incount, MPI::Request array_of_requests[], int array_of_indices[], MPI::Status array_of_statuses[]) Если один или более обменов, завершенных MPI_WAITSOME , не могут быть выполнены, надо возвращать по каждому обмену специ- фическую информацию. Аргументы outcount, array_of_indices и array_of_statuses будут индицировать завершение всех обменов, успешных или неуспешных. Вызов будет возвращать код ошибки MPI_ERR_IN_STATUS и устанавливать поле ошибки каждого возвращенного статуса, чтобы указать на успешное завершение или возвратить специфический код ошибки. Вызов будет возвращать MPI_SUCCESS , если ни один запрос не содержал ошибки, и будет возвращен другой код ошибки, если запрос не может быть выполнен по какой-то причине. В таких случаях поля ошибок статуса не будут корректироваться. Функция MPI_TESTSOME ведет себя подобно MPI_WAITSOME за исключением того, что заканчивается немед- ленно. Если ни одной операции не завершено, она возвращает outcount = 0 . Если не имеется активных дескрипторов в списке, она возвращает outcount = MPI_UNDEFINED 76 MPI_TESTSOME (incount, array_of_requests, outcount, array_of_indices, array_of_statuses) IN incount длина массива запросов (целое) IN OUT array_of_requests массив запросов (массив дескрипторов) OUT outcount число завершенных запросов (целое) OUT array_of_indices массив индексов завершенных операций (массив целых) OUT array_of_statuses массив статусных объектов завершенных операций (массив статусов) int MPI_Testsome (int incount, MPI_Request *array_of_requests, int *outcount, int *array_of_indices, MPI_Status *array_of_statuses) MPI_TESTSOME (INCOUNT, ARRAY_OF_REQUESTS, OUTCOUNT, ARRAY_OF_INDICES, ARRAY_OF_STATUSES, IERROR) INTEGER INCOUNT, ARRAY_OF_REQUESTS(*), OUTCOUNT, ARRAY_OF_INDICES(*), ARRAY_OF_STATUSES(MPI_STATUS_SIZE,*), IERROR static int MPI::Request::Testsome(int incount, MPI::Request array_of_requests[], int array_of_indices[], MPI::Status array_of_statuses[]) MPI_TESTSOME является локальной операцией, которая закан- чивается немедленно, тогда как MPI_WAITSOME будет блокиро- ваться до завершения обменов, если в списке содержится хотя бы один активный дескриптор. Оба вызова выполняют требование одно- значности: если запрос на прием повторно появляется в списке запро- сов, передаваемых MPI_WAITSOME или MPI_TESTSOME , и соот- ветствующая посылка была инициирована, тогда прием будет завер- шен успешно, если передача не закрыта другим приемом. Пример 3.13. Код клиент – сервер (невозможность обмена). CALL MPI_COMM_SIZE(comm, size, ierr) CALL MPI_COMM_RANK(comm, rank, ierr) ! код клиента IF(rank > 0) THEN DO WHILE(.TRUE.) CALL MPI_ISEND(a, n, MPI_REAL, 0, tag, comm, request, ierr) CALL MPI_WAIT(request, status, ierr) END DO ELSE ! rank=0 – код сервера DO i=1, size-1 CALL MPI_IRECV(a(1,i),n,MPI_REAL,i tag,comm,request_list(i),ierr) END DO 77 DO WHILE(.TRUE.) CALL MPI_WAITANY(size-1, request_list, index, status, ierr) CALL DO_SERVICE(a(1,index)) ! дескриптор одного сообщения CALL MPI_IRECV(a(1,index),n,MPI_REAL,index,tag,comm, request_list(index), ierr) END DO END IF Пример 3.14. Код с использованием MPI_WAITSOME. CALL MPI_COMM_SIZE(comm, size, ierr) CALL MPI_COMM_RANK(comm, rank, ierr) ! код клиента IF(rank > 0) THEN DO WHILE(.TRUE.) CALL MPI_ISEND(a, n, MPI_REAL, 0, tag, comm, request, ierr) CALL MPI_WAIT(request, status, ierr) END DO ELSE ! rank=0 – код сервера DO i=1, size-1 CALL MPI_IRECV(a(1,i), n, MPI_REAL,i,tag,comm, requests(i), ierr) END DO DO WHILE(.TRUE.) CALL MPI_WAITSOME(size,request_list,numdone,indices,statuses, ierr) DO i=1, numdone CALL DO_SERVICE(a(1, indices(i))) CALL MPI_IRECV(a(1, indices(i)), n, MPI_REAL, 0, tag, comm, requests(indices(i)), ierr) END DO END DO END IF 3.8. ПРОБА И ОТМЕНА Операции MPI_PROBE и MPI_IPROBE позволяют проверить входные сообщения без реального их приема. Пользователь затем мо- жет решить, как ему принимать эти сообщения, основываясь на ин- формации, возвращенной при пробе (преимущественно на информа- ции, возвращенной аргументом status ). В частности, пользователь может выделить память для приемного буфера согласно длине опро- бованного сообщения. Операция MPI_CANCEL позволяет отменить ждущие сообщения. Это необходимо для очистки. Инициация операций получения или от- правки связывает пользовательские ресурсы, и может оказаться необ- ходимой отмена, чтобы освободить эти ресурсы. 78 MPI_IPROBE (source, tag, comm, flag, status) IN source номер процесса-отправителя или MPI_ANY_SOURCE (целое) IN tag значение тэга или MPI_ANY_TAG (целое) IN comm коммуникатор (дескриптор) OUT flag (логическое значение) OUT status статус (статус) int MPI_Iprobe(int source, int tag, MPI_Comm comm, int *flag, MPI_Status *status) MPI_IPROBE(SOURCE, TAG, COMM, FLAG, STATUS, IERROR) LOGICAL FLAG INTEGER SOURCE, TAG, COMM, STATUS(MPI_STATUS_SIZE), IERROR bool MPI::Comm::Iprobe(int source, int tag, MPI::Status& status) const MPI_IPROBE ( source, tag, comm, flag, status ) возвращает flag = true , если имеется сообщение, которое может быть получено и кото- рое соответствует образцу, описанному аргументами source , tag , и comm . Вызов соответствует тому же сообщению, которое было бы получено с помощью вызова MPI_RECV (..., source, tag, comm, status ), выполненного на той же точке программы, и возвращает ста- тус с теми же значениями, которые были бы возвращены MPI_RECV() . Другими словами, вызов возвращает flag = false и ос- тавляет статус неопределенным. Если MPI_IPROBE возвращает flag = true , тогда содержание статусного объекта может быть впоследст- вии получено, как описано в параграфе 3.2.5, чтобы определить ис- точник, тэг и длину опробованного сообщения. Последующий прием, выполненный с тем же самым контекстом и тэгом, возвращенным в status вызовом MPI_IPROBE , будет получать сообщение, которое соответствует пробе, если после пробы не вмешается какое-либо дру- гое сообщение. Если принимающий процесс многопоточный, ответст- венность за выполнение условия возлагается на пользователя. MPI_PROBE (source, tag, comm, status) IN source номер источника или MPI_ANY_SOURCE (целое) IN tag значение тэга или MPI_ANY_TAG (целое) IN comm коммуникатор (дескриптор) OUT status статус (статус) int MPI_Probe(int source, int tag, MPI_Comm comm, MPI_Status *status) MPI_PROBE(SOURCE, TAG, COMM, STATUS, IERROR) INTEGER SOURCE, TAG, COMM, STATUS(MPI_STATUS_SIZE), IERROR void MPI::Comm::Probe(int source, int tag, MPI::Status& status) const 79 MPI_PROBE ведет себя подобно MPI_IPROBE , исключая то, что функция MPI_PROBE является блокирующей и заканчивается после того, как соответствующее сообщение было найдено. Аргумент source функции MPI_PROBE может быть MPI_ANY_SOURCE , это позволяет опробовать сообщения из произ- вольного источника и/или с произвольным тэгом. Однако специфиче- ский контекст обмена обязан создаваться только при помощи аргу- мента comm . Сообщение не обязательно должно быть получено сразу после опробования, оно может опробоваться несколько раз перед его получением. MPI–реализация MPI_PROBE и MPI _ IPROBE нуждается в га- рантии продвижения: если обращение к MPI_PROBE уже было за- пущено процессом и посылка, которая соответствует пробе, уже ини- циирована тем же процессом, то вызов MPI_PROBE будет завершен, если сообщение не получено другой конкурирующей операцией приема (которая выполняется другой ветвью опробуемого процесса). Аналогично, если процесс ожидает выполнения MPI_IPROBE и соответствующее сообщение было запущено, то обращение к MPI_IPROBE возвратит flag = true , если сообщение не получено другой конкурирующей приемной операцией. Пример 3.15. Использование блокируемой пробы для ожидания входного сообщения. CALL MPI_COMM_RANK(comm, rank, ierr) IF (rank.EQ.0) THEN CALL MPI_SEND(i, 1, MPI_INTEGER, 2, 0, comm, ierr) ELSE IF(rank.EQ.1) THEN CALL MPI_SEND(x, 1, MPI_REAL, 2, 0, comm, ierr) ELSE ! rank.EQ.2 DO i=1, 2 CALL MPI_PROBE(MPI_ANY_SOURCE, 0, comm, status, ierr) IF (status(MPI_SOURCE) = 0) THEN 100 CALL MPI_RECV(i,1,MPI_INTEGER,0,0,comm, status, ierr) ELSE 200 CALL MPI_RECV(x,1,MPI_REAL,1,0,comm, status, ierr) END IF END DO END IF Каждое сообщение принимается с правильным типом. 80 Пример 3.16. Некорректная программа с использованием блокируе- мой пробы для ожидания входного сообщения. CALL MPI_COMM_RANK(comm, rank, ierr) IF (rank.EQ.0) THEN CALL MPI_SEND(i, 1, MPI_INTEGER, 2, 0, comm, ierr) ELSE IF(rank.EQ.1) THEN CALL MPI_SEND(x, 1, MPI_REAL, 2, 0, comm, ierr) ELSE DO i=1, 2 CALL MPI_PROBE(MPI_ANY_SOURCE, 0,comm, status, ierr) IF (status(MPI_SOURCE) = 0) THEN 100 CALL MPI_RECV(i,1,MPI_INTEGER,MPI_ANY_SOURCE, 0,comm,status, ierr) ELSE 200 CALL MPI_RECV(x,1,MPI_REAL,MPI_ANY_SOURCE,0, comm,status,ierr) END IF END DO END IF Модифицируем пример 3.15, используя MPI_ANY_SOURCE , как аргумент sourse в двух вызовах приема, обозначенных метками 100 и 200. Теперь программа некорректна: операция приема может получать сообщение, которое отличается от сообщения, опробованного преды- дущим обращением к MPI_PROBE MPI_CANCEL (request) IN request коммуникационный запрос (дескриптор) int MPI_Cancel(MPI_Request *request) MPI_CANCEL(REQUEST, IERROR) INTEGER REQUEST, IERROR void MPI::Request::Cancel () const Обращение к MPI_CANCEL маркирует для отмены ждущие не- блокирующие операции обмена (передача или прием). Вызов cancel является локальным. Он заканчивается немедленно, возможно перед действительной отменой обмена. После маркировки необходимо за- вершить эту операцию обмена, используя вызов MPI_WAIT или MPI_TEST (или любые производные операции). Если обмен отмечен для отмены, то вызов MPI_WAIT для этой операции гарантирует за- 81 вершение, не глядя на активность других процессов (то есть MPI_WAIT ведет себя как локальная функция); аналогично, если MPI_TEST вызывается повторно в цикле занятого ожидания для от- мены обмена, тогда MPI_TEST будет неизбежно успешно закончен. Успешная отмена буферизованной передачи освобождает буферное пространство, занятое ждущим сообщением. Должно выполняться следующее условие: либо отмена имеет ус- пех, либо имеет успех обмен, но не обе ситуации вместе. Если переда- ча маркирована для отмены, то обязательно должна быть ситуация, что когда-либо передача завершается нормально (посланное сообще- ние принято процессом назначения) или передача отменена успешно (никакая часть сообщения не принята по адресу назначения). Тогда любой соответствующий прием закрывается другой передачей. Если прием маркирован для отмены, то обязан быть случай, когда прием завершился нормально или этот прием успешно отменен (никакая часть приемного буфера не изменена). Тогда любая соответствующая передача должна быть удовлетворена другим приемом. Если операция была отменена, тогда информация об этом будет возвращена в аргу- мент статуса операции, которая завершает обмен. |