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

5.2.2  Синхронный блокирующий обмен

При синхронном обмене адресат посылает источнику уведомление о завершении приема. Только после получения этого уведомления обмен считается завершенным и источник "знает", что его сообщение получено. Синхронная передача выполняется с помощью подпрограммы MPI_Ssend:

intMPI_Ssend(void *buf, intcount, MPI_Datatype

datatype, int dest, int tag, MPI_Comm comm)

Параметры у нее такие же, как и у подпрограммы  MPI_Send.

Если процесс выполняет блокирующую синхронную передачу до того, как другой процесс попытается получить сообщение, он приостанавливается до приема сообщения адресатом. Синхронный обмен медленнее, чем стандартный, но он безопаснее, поскольку не дает коммуникационной сети переполниться не дошедшими до адресата, потерявшимися в сети, сообщениями. Этим обеспечивается большая степень предсказуемости поведения параллельной программы. Благодаря отсутствию потерявшихся, "невидимых" сообщений, проще оказывается и отладка программы.

Передача сообщения в синхронном режиме может быть начата независимо от того, был ли зарегистрирован его прием, но она считается успешно выполненной только при наличии соответствующего приема. Завершение синхронной передачи означает не только то, что буфер передачи можно использовать заново, но и то, что адресат начал выполнение приема. Если и передача, и прием являются блокирующими операциями, обмен не завершится, пока оба процесса не начнут передачу и прием сообщения. Операция передачи в этом режиме нелокальная.

5.2.3  Буферизованный обмен

Передача сообщения в буферизованном режиме может быть начата независимо от того, зарегистрирован ли соответствующий прием. Источник копирует сообщение в буфер, а затем передает его в неблокирующем режиме так же, как в стандартном режиме. Эта операция локальна, поскольку ее выполнение не зависит от наличия соответствующего приема. Если объем буфера недостаточен, возникает ошибка. Выделение буфера и его размер контролируются программистом.

Буферизованная передача завершается сразу, поскольку сообщение немедленно копируется в буфер для последующей передачи. В отличие от стандартного обмена, в этом случае работа источника и адресата не синхронизована. Параметры подпрограммы буферизованного обмена MPI_Bsend:

intMPI_Bsend(void *buf, intcount, MPI_Datatype

datatype, int dest, int tag, MPI_Comm comm)

такие же, как и у MPI_Send.

При выполнении буферизованного обмена программист должен заранее создать буфер достаточного размера с помощью вызова подпрограммы:

int MPI_Buffer_attach(void *buf, size)

В результате вызова создается буфер с именем buf и размером size в байтах, который можно использовать только один раз, после чего его нужно отключить путем вызова подпрограммы отключения:

int MPI_Buffer_detach(void *buf, int *size)

При выполнении отключения возвращается адрес (buf) и размер отключаемого буфера (size). Эта операция блокирует работу процесса до тех пор, пока все сообщения, находящиеся в буфере, не будут обработаны. Благодаря этому, вызов данной подпрограммы можно использовать для форсированной передачи сообщений. После завершения вызова можно вновь использовать память, которую занимал буфер, однако следует помнить, что в языке С данный вызов не освобождает автоматически память, отведенную для буфера. Пример использования подпрограмм подключения и отключения буфера приведен в тексте 5.5.

Текст 5.5. Пример использования буферизованного обмена

#include "mpi.h"

#include <stdio.h>

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

{

int bf;                            /* имя буфера */

int myrank;

MPI_Status status;

int bfs = 1;           /* размер буфера */

int TAG = 0;

MPI_Init(&argc, &argv);

MPI_Comm_rank(MPI_COMM_WORLD, &myrank);

if (myrank ==0)

then

{

bf = (int *) malloc(bfs + MPI_BSEND_OVERHEAD);

MPI_Buffer_attach(bf, bfs + MPI_BSEND_OVERHEAD);

bf = (int *) 10;

MPI_Bsend(&bf, bfs, MPI_INT, 1, TAG,

MPI_COMM_WORLD);

MPI_Buffer_detach(&bf, &bfs);

}

else

{

MPI_Recv(&bf, bfs, MPI_INT, 0, TAG,