Параллельное программирование: Учебное пособие, страница 95

Объявление подпрограммы MPI_Sendrecv, выполняющей прием и передачу данных с блокировкой, выглядит следующим образом:

int MPI_Sendrecv(void *sendbuf, int sendcount,

MPI_Datatype sendtype, int dest, int sendtag,

void *recvbuf, int recvcount, MPI_Datatype

recvtype, int source, int recvtag,

MPI_Comm comm, MPI_Status *status)

где входными формальными параметрами являются:

·  sendbuf — начальный адрес буфера передачи;

·  sendcount — количество передаваемых элементов;

·  sendtype — тип передаваемых элементов;

·  dest — ранг адресата;

·  sendtag — тег передаваемого сообщения;

·  recvbuf — начальный адрес буфера приема;

·  recvcount — количество элементов в буфере приема;

·  recvtype — тип элементов в буфере приема;

·  source — ранг источника;

·  recvtag — тег принимаемого сообщения;

·  comm — коммуникатор.

Выходные параметры: recvbuf — начальный адрес буфера приема и status — статус операции приема. И прием, и передача используют один и тот же коммуникатор. Буферы передачи и приема не должны пересекаться, у них может быть разный размер, типы пересылаемых и принимаемых данных также могут различаться.

Общий буфер для передачи и для приема сообщений в блокирующем режиме используется в подпрограмме MPI_Sendrecv_replace, объявление и параметры которой имеют следующий вид и назначение:

int MPI_Sendrecv_replace(void *buf, int count,

MPI_Datatype datatype, int dest, int sendtag,

int source, int recvtag, MPI_Comm comm,

MPI_Status *status)

·  count — количество отправляемых данных и емкость буфера приема;

·  datatype — тип данных в буфере приема и передачи;

·  dest — ранг адресата;

·  sendtag — тег передаваемого сообщения;

·  source — ранг источника;

·  recvtag — тег принимаемого сообщения;

·  comm — коммуникатор.

Выходные параметры: buf — начальный адрес буфера приема и передачи и статус (status). Принимаемое сообщение не должно превышать по размеру отправляемое сообщение, а передаваемые и принимаемые данные должны быть одного типа. Последовательность приема и передачи выбирается системой автоматически.

Большинство реализаций MPI гарантируют соблюдение порядка сообщений при приеме, обеспечивая детерминированное поведение параллельной программы, которая выполняет процессы в одном потоке. Нарушить детерминированное поведение программы могут вызовы подпрограмм MPI_Cancel и MPI_Waitany.

Пример программы с передачей и приемом сообщений, порядок которых сохраняется при приеме, приведен в тексте 5.8.

Текст 5.8. Передача и прием с сохранением порядка

#include "mpi.h"

#include <stdio.h>

int main(int argc, char *argv[])

{

int rank, tag, cnt, status(MPI_STATUS_SIZE);

float sndbuf1, sndbuf2, rcvbuf;

parameter(bufsize = 4 + MPI_BSEND_OVERHEAD);

byte buff(bufsize);

int cnt = 1;

int tag = 0;

MPI_Init(&argc, &argv);

MPI_Comm_rank(MPI_COMM_WORLD, &myrank);

if (rank == 0)

{

sndbuf1 = 3.14159;

MPI_Buffer_attach(&buff, bufsize);

MPI_Bsend(&sndbuf1, cnt, MPI_FLOAT, 1, tag,

MPI_COMM_WORLD);

printf("Process %i ", rank, "send %i\n ", sndbuf1);

sndbuf2 = 2.71828;

MPI_Bsend(&sndbuf2, cnt, MPI_FLOAT, 1, tag,

MPI_COMM_WORLD);

printf("process %i", rank, " send %i\n ", sndbuf2);

MPI_Buffer_attach(&buff, ibufsize);

}

else

{

MPI_Recv(&rcvbuf, cnt, MPI_FLOAT, 0, tag,

MPI_COMM_WORLD, status);

printf("process %i",rank," received %i\n", rcvbuf);

MPI_Recv(&rcvbuf, cnt, MPI_FLOAT, 0, tag,

MPI_COMM_WORLD, status);

printf("process %i",rank," received %i\n", rcvbuf);

}

MPI_Finalize();

return 0;

}

Первый вызов подпрограммы приема обеспечивает прием сообщения, которое было отправлено первым, а сообщение, отправленное вторым, будет получено при втором вызове этой подпрограммы.