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

if (my_rank == 0)

{

        for (i = 0; i < 50; i++)

            vector[i] = 0.0;

        for (i = 50; i < 100; i++)

            vector[i] = 1.0;

        MPI_Send(vector+50, 50, MPI_FLOAT, 1, 0,

                                     MPI_COMM_WORLD);

      }

     else

      {    /* my_rank == 1 */

        MPI_Recv(vector+50, 50, MPI_FLOAT, 0, 0,

                             MPI_COMM_WORLD, &status);

        for (i = 50; i < 100; i++)

            printf("%3.1f ",vector[i]);

        printf("\n");

}

MPI_Finalize();

} /* main */

Размер полученного сообщения (count) можно определить с помощью вызова подпрограммы MPI_Get_count:

int MPI_Get_count(MPI_Status *status,

MPI_Datatype datatype, int *count)

Аргумент datatype должен соответствовать типу данных, указанному в операции обмена.

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

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

Процесс_0

Процесс_1

MPI_Init();

MPI_Send(dest=1);

MPI_Finalize();

¾¾¾®

MPI_Init();

MPI_Recv(source=0);

MPI_Finalize();

Рис. 5.2.Схема простейшей программы с двухточечным обменом

Если во втором процессе не предусмотрен прием отправленного ему сообщения, программу следует считать ошибочной (рис. 5.3).

Процесс_0

Процесс_1

MPI_Init();

MPI_Send(dest=1);

MPI_Finalize();

¾¾¾® ?

MPI_Init();

MPI_Finalize();

Рис. 5.3.Схема ошибочной программы с двухточечным обменом

Простой пример законченной MPI-программы с двухточечным обменом приведен в тексте 5.1.

Текст 5.1. Стандартный блокирующий обмен. Вариант 1.

#include "mpi.h"

#include <stdio.h>

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

{

int myid, numprocs;

char message[24];

int myrank;

MPI_Status status;

int tag = 0;

MPI_Init(&argc, &argv);

MPI_Comm_rank(MPI_COMM_WORLD, &myrank);

if (myrank == 0)

{

strcpy(message, "Hi, Parallel Programmer!");

MPI_Send(&message, 25, MPI_CHAR, 1, tag,

MPI_COMM_WORLD);

}

else

{

MPI_Recv(&message, 25, MPI_CHAR, 0, tag,

MPI_COMM_WORLD, &status);

printf("received: %s\n", message);

}

MPI_Finalize();

return 0;

}

В этом примере процесс с рангом 0 передает сообщение процессу с рангом 1, используя для этого подпрограмму MPI_Send. При выполнении этой операции в памяти процесса-отправителя выделяется буфер передачи с именем message. В буфере размещается 24 символа сообщения (Hi, Parallel Programmer!). Процесс с рангом 1 принимает сообщение с помощью подпрограммы MPI_Recv. Сообщение сохраняется на приемной стороне в буфере с аналогичным идентификатором message. Следующие два аргумента подпрограммы приема определяют размер и тип данных, помещаемых в буфер приема. Результат выполнения этой программы:

mpiexechostHM1, HM2 -n 2 -- myprogr

received: Hi, Parallel Programmer!

В первой строке приведена командная строка запуска программы c именем myprogr  на двух (-n 2) главных машинах: HM1 – хозяине (ранг 0) и HM2 – клиенте (ранг 1, согласно порядку перечисления названий главных машин). Здесь и далее будем полагать, что имя исполняемой программы –myprogr.

Пример программы, в котором сообщениями обмениваются процессы с четными и нечетными рангами, дан в тексте 5.2. Предполагается, что значение size четно.

Текст 5.2. Стандартный блокирующий обмен. Вариант 2.

#include "mpi.h"