Функция приема сообщения с блокировкой:
int MPI_Recv(void* buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status);
где:
OUT buf – адрес начала расположения принимаемого сообщения;
count – максимальное число принимаемых элементов;
datatype – тип элементов принимаемого сообщения;
source – номер процесса-отправителя или MPI_ANY_SOURCE;
tag – числовой идентификатор сообщения или MPI_ANY_TAG;
comm – идентификатор группы;
OUT status –параметры принятого сообщения (описание типа MPI_Status см. в п. 3.1 при первом упоминании в описании параметров функции MPI_Wait).
Функция выполняет прием count элементов типа datatype сообщения с идентификатором tag от процесса с номером source в группе с идентификатором comm.
Число элементов в принимаемом сообщении не должно превосходить значения count. Если число принятых элементов меньше значения count, то гарантируется, что в буфере buf изменятся только элементы, соответствующие элементам принятого сообщения. Попытка считать сообщение с параметром count меньше, чем число элементов в буфере, приводит к потере сообщения.
Блокировка гарантирует, что после возврата из функции все элементы сообщения будут уже приняты и расположены в буфере buf.
В качестве номера процесса-отправителя можно указать предопределенную константу MPI_ANY_SOURCE – признак того, что подходит сообщение от любого процесса. В качестве идентификатора принимаемого сообщения можно указать константу MPI_ANY_TAG – признак того, что подходит сообщение с любым числовым идентификатором.
Примечание. Следует отметить асимметрию между операциями посылки и приема. Операция приема допускает получение сообщения от произвольного отправителя, в то время как в операции посылки должен быть указан уникальный числовой идентификатор процесса-получателя.
Пример №3 (в качестве практического занятия дописать).
Дано: процессу №0 (значение переменной «int NP;») необходимо принять значение в одну переменную «double a;» с любого другого процесса. Передача в данном примере не рассматривается, но известно, что процесс с №1 примерно в это же время передал одно значение типа double процессу №0.
if(_ _ _ _ _ _)
{
MPI_Recv(_ _ _ _
}
(конец примера №3)
Если заранее невозможно определить число count – максимально возможное количество принимаемых элементов, то можно воспользоваться следующей функцией.
Функция для определения параметров поступающего сообщения без его чтения с блокировкой:
int MPI_Probe(int source, int tag, MPI_Comm comm, MPI_Status *status);
где:
source – номер процесса-отправителя или MPI_ANY_SOURCE;
tag – числовой идентификатор ожидаемого сообщения или MPI_ANY_TAG;
comm – идентификатор группы;
OUT status – параметры обнаруженного сообщения.
Функция MPI_Probe выполняется с блокировкой, поэтому завершится она лишь тогда, когда сообщение с подходящим идентификатором и номером процесса-отправителя будет доступно для получения. Следует обратить внимание, что функция определяет только факт прихода сообщения, но реально его не принимает.
С помощью возвращенной информации в переменной status (и вызова MPI_Get_count) пользователь может выделить необходимый объем памяти для буфера приёма (для функции MPI_Probe).
Функция приема сообщения без блокировки:
int MPI_Irecv(void* buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Request *request);
где:
OUT buf – адрес начала буфера приема сообщения;
count – максимальное число элементов в принимаемом сообщении;
datatype – тип элементов принимаемого сообщения;
source – номер процесса-отправителя или MPI_ANY_SOURCE;
tag – числовой идентификатор принимаемого сообщения или MPI_ANY_TAG;
comm – идентификатор группы;
OUT request – значение, используемое при завершении операции приема.
Прием сообщения аналогичен MPI_Recv, однако возврат из функции происходит сразу после инициализации процесса приема без ожидания получения сообщения в буфере buf. Окончание процесса приема можно определить с помощью параметра request и функций MPI_Wait и MPI_Test.
Как и в блокирующих операциях часто возникает необходимость опроса параметров полученного сообщения без его фактического чтения (до фактического чтения). Это делается с помощью функции MPI_Iprobe.
Функция для определения поступления сообщения и определения параметров поступленного сообщения без его чтения без блокировки:
int MPI_Iprobe(int source, int tag, MPI_Comm comm, int *flag, MPI_Status *status);
где:
source – номер процесса-отправителя или MPI_ANY_SOURCE;
tag – числовой идентификатор ожидаемого сообщения или MPI_ANY_TAG;
comm – идентификатор группы;
OUT flag – признак завершенности операции обмена;
OUT status – параметры обнаруженного сообщения.
Получение информации о поступлении и структуре ожидаемого сообщения без блокировки (и может вызываться несколько раз перед получением сообщения). В параметре flag возвращается значение 1 (логическое TRUE), если сообщение с подходящими номером процесса-отправителя, идентификатором сообщения и идентификатором группы уже может быть принято. В этом случае ее действие полностью аналогично действию функции MPI_Probe. В параметре flag возвращается значение 0 (логическое FALSE), если сообщения с указанными атрибутами еще нет.
Для определения числа фактически полученных (или доступных для получения) элементов сообщения необходимо использовать специальную функцию:
int MPI_Get_count(MPI_Status *status, MPI_Datatype datatype, int *count);
где:
status – параметры сообщения;
datatype – тип элементов принятого сообщения;
OUT count – число полученных элементов (иногда может принимать значение MPI_UNDEFINED).
Функция MPI_Get_count может быть вызвана либо после чтения сообщения при помощи функций MPI_Recv, MPI_Irecv, либо после опроса факта поступления сообщения при помощи функций MPI_Probe, MPI_Iprobe.
Как отмечалось ранее, воспользоваться результатом неблокирующей операции обмена или повторно использовать ее параметры можно только после ее полного завершения. Имеется два типа функций завершения неблокирующих операций:
- Функции ожидания завершения семейства WAIT блокируют работу процесса до полного завершения операции.
- Функции проверки завершения семейства TEST возвращают значения TRUE или FALSE в зависимости от того, завершилась операция или нет. Они не блокируют работу процесса и полезны для предварительного определения факта завершения операции.
- Функции снятия запроса без ожидания завершения операции.
В случае приема, параметры и длину полученного сообщения можно определить обычным образом с помощью параметра status.