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

Необходимо отметить и еще одну особенность двухточечного обмена: если два процесса инициировали передачу и прием сообщения, то, по крайней мере, одна из этих операций будет выполнена. Так, например, передача будет выполнена, если только адресат не примет другое сообщение. Операция по приему будет выполнена в том случае, если сообщение не будет перехвачено другим процессом, выполняющим обмен с тем же источником. Этот случай отражен в тексте 5.9.

Текст 5.9. Пример перехвата сообщений

#include "mpi.h"

#include <stdio.h>

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

{

int rank, tag1, tag2, cnt, status(MPI_STATUS_SIZE);

float sndbuf1, sndbuf2, rcvbuf1, rcvbuf2;

parameter(bufsize = 4 + MPI_BSEND_OVERHEAD);

byte buff(bufsize);

int cnt = 1;

int tag1 = 0;

int tag2 = 1;

sndbuf1 = 3.14159;

sndbuf2 = 2.71812;

MPI_Init(&argc, &argv);

MPI_Comm_rank(MPI_COMM_WORLD, &myrank);

if (rank == 0)

{

MPI_Buffer_attach(&buff, bufsize);

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

MPI_COMM_WORLD);

printf(process ", rank, " send ", sndbuf1);

MPI_Buffer_detach(&buff, ibufsize);

MPI_Ssend(&sndbuf2, cnt, MPI_FLOAT, 1, tag2,

MPI_COMM_WORLD);

printf("process ", rank, " send ", sndbuf2);

}

else

{

MPI_Recv(&rcvbuf1, cnt, MPI_FLOAT, 0, tag2,

MPI_COMM_WORLD, status);

printf("process ", rank, " received ", rcvbuf1);

MPI_Recv(&rcvbuf2, cnt, MPI_FLOAT, 0, tag1,

MPI_COMM_WORLD, status);

printf("process ", rank, ." received ", rcvbuf2);

}

MPI_Finalize();

return 0;

}

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

mpiexec –host -machinefile -n 2 -- myprogr

process 0 send 3.14159012

process 0 send 2.71828004

process 1 received 3.14159012

process 1 received 2.71828004

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

Существуют ситуации, невольно создаваемые программистами, в которых MPI не гарантирует правильной обработки обменов. Например, если процессом 0 отправлено сообщение процессу 1, а адресат (1) осуществляет периодически повторяющиеся запросы на прием, то он может принять взамен сообщение от другого процесса, который свои сообщения каждый раз отправляет раньше, чем процесс 0. И может случиться так, что сообщение от процесса 0 никогда не будет принято. Программист должен при распараллеливании программы учитывать временные параметры, характеризующие вычислительный процесс и обмен данными, чтобы оставаться в пределах ограниченных ресурсов параллельной вычислительной среды. Например, операция буферизованной передачи из-за недостаточного объема буфера может привести к аварийному останову программы.

5.2.7. Неблокирующие операции обмена

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