then
{
i = 2004;
MPI_Send(i, 1, MPI_INTEGER, dest, tag,
MPI_COMM_WORLD);
}
else
{
if(rank == 1)
{
x = 3.14159;
MPI_Send(x, 1, MPI_FLOAT, dest, tag,
MPI_COMM_WORLD);
}
else
{
for(k = 1, 2;;)
{
MPI_Probe(MPI_Any_source, tag,
MPI_COMM_WORLD, status);
if (status(MPI_Source) == 0)
{
MPI_Recv(i, 1, MPI_INT, 0, tag,
MPI_COMM_WORLD, status);
Printf("received ", i, " from 0");
}
else
{
MPI_Recv(x, 1, MPI_FLOAT, 1, tag,
MPI_COMM_WORLD, status);
Printf("received ", x, " from 1");
}
}
}
MPI_Finalize();
return 0;
}
В этом примере проблема заключается в том, что процессы с рангами 0 и 1 передают процессу dest=2 сообщения, содержащие данные разных типов. Порядок приема этих сообщений не определен, поэтому заранее неизвестно, данные какого типа должны быть приняты при первом вызове подпрограммы MPI_Recv, а какие — при втором. Благодаря вызову подпрограммы MPI_Probe, каждое сообщение принимается с использованием правильного типа данных.
В тексте 5.7 подпрограммы-пробники принимают сообщения от неизвестного источника, количество элементов целого типа в котором тоже неизвестно. В этом случае вместо ранга источника и тега сообщения используются джокеры. Сначала с помощью вызова подпрограммы MPI_Probe фиксируется факт наличия еще не принятого сообщения. Затем определяется источник сообщения, с помощью вызова MPI_Get_count определяется его длина, выделяется буфер подходящего размера и лишь потом выполняется прием сообщения.
#include "mpi.h"
#include <stdio.h>
int main(int argc, char *argv[])
{
int myid, numprocs, **buf, source, i;
int message[3] = {0, 1, 2};
int myrank, data = 2004, count, TAG = 0;
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
if (myrank == 0)
{
MPI_Send(&data, 1, MPI_INT, 2, TAG,
MPI_COMM_WORLD);
}
else
if (myrank ==1)
{
MPI_Send(&message, 3, MPI_INT, 2, TAG,
MPI_COMM_WORLD);
}
else
{
MPI_Probe(MPI_ANY_SOURCE, 0, MPI_COMM_WORLD,
&status);
source = status.MPI_SOURCE;
MPI_Get_count(&status, MPI_INT, &count);
for (i = 0; i < count; i++)
{
buf[i] = (int *)malloc(count *sizeof(int));
}
MPI_Recv(&buf[0], count, MPI_INT, source, TAG,
MPI_COMM_WORLD, &status);
for (i = 0; i < count; i++)
{
printf ("received: %d\n", buf[i]);
}
}
MPI_Finalize();
return 0;
}
При запуске этой программы должны создаваться три процесса:
mpiexec –host-machinefile -n 3 -- myprogr
Процесс с рангом 0 передает процессу 2 сообщение, содержащее одно значение (переменная data), а процесс с рангом 1 передает тому же процессу три элемента данных в массиве message. Порядок поступления этих сообщений не определен и первым может прийти как сообщение от процесса 0, так и сообщение от процесса 1. Для того чтобы правильно организовать прием сообщения, необходимо заранее узнать его длину и, возможно, источник. Это и делают подпрограммы MPI_Probe и MPI_Get_count. В этой программе будет принято лишь одно сообщение, а второе останется в коммуникационной среде. В нормальных программах таких ситуаций не должно быть.
Рисунок 5.5.Обмен сообщениями по кольцу из процессов.
В случае применения для сдвига блокирующих операций передачи и приема, очень важно правильно определить порядок их выполнения, иначе взаимные зависимости между процессами могут привести к тупиковым ситуациям. Например, можно сделать так, чтобы вначале на передачу работали четные процессы, а на прием – нечетные. Затем их операции меняются на противоположные. Соблюдение правильной последовательности обменов в процессе выполнения операций приемопередачи осуществляется самой системой. При этом подпрограммы приемопередачи могут взаимодействовать с обычными подпрограммами обмена и подпрограммами зондирования.
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.