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

Интеробмен возможен, только если создан соответствующий интеркоммуникатор, а это можно сделать с помощью подпрограммы MPI_Intercomm_create:

int MPI_Intercomm_create(MPI_Comm local_comm,

int local_leader, MPI_Comm peer_comm,

int remote_leader, int tag,

MPI_Comm *new_intercomm)

Входные параметры этой подпрограммы:

·  local_comm — локальный интракоммуникатор;

·  local_leader — ранг лидера в локальном коммуникаторе (обычно процесс с рангом 0);

·  рееr_соmm — удаленный коммуникатор;

·  remote_leader — ранг лидера в удаленном коммуникаторе (обычно процесс с рангом 0);

·  tag — тег интеркоммуникатора, используемый лидерами обеих групп для обменов в контексте родительского коммуникатора.

Выходной параметр — интеркоммуникатор (new_intercomm). "Джокеры" в качестве параметров использовать нельзя. Вызов этой подпрограммы должен выполняться в обеих группах процессов, которые должны быть связаны между собой. При этом в каждом из этих вызовов используется локальный интракоммуникатор, соответствующий данной группе процессов. При работе с MPI_Intercomm_create локальная и удаленная группы процессов не должны пересекаться, иначе возможны "тупики".

Пример организации обмена между разными группами с помощью интеркоммуникатора приведен в тексте 5.15.

Текст 5.15. Пример создания интеркоммуникатора

#include "mpi.h"

#include <stdio.h>

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

{

int counter, message, myid, numprocs, server;

int color, remote_leader_rank, i, ICTAG = 0;

MPI_Status status;

MPI_Comm oldcommdup, splitcomm, oldcomm, inter_comm;

MPI_Init(&argc, &argv);

oldcomm = MPI_COMM_WORLD;

MPI_Comm_dup(oldcomm, &oldcommdup);

MPI_Comm_size(oldcommdup, &numprocs);

MPI_Comm_rank(oldcommdup, &myid);

server = numprocs — 1;

color = (myid == server);

MPI_Comm_split(oldcomm, color, myid, &splitcomm);

if(!color)

{

remote_leader_rank = server;

}

else

{

remote_leader_rank = 0;

}

MPI_Intercomm_create(splitcomm, 0, oldcommdup,

remote_leader_rank, ICTAG, &inter_comm);

MPI_Comm_free (&oldcommdup) ;

if (myid == server)

{

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

{

MPI_Recv(&message, 1, MPI_INT, i,

MPI_ANY_TAG, inter_comm, &status);

printf("Process rank %i received %i from %i\n",

 myid, message, status.MPI_SOURCE);

}

}

else

{

counter = myid;

MPI_Send(&counter, I, MPI_INT,  0, 0, inter_comm);

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

}

MPI_Comm_free(&inter_comm);

MPI_Finalize();

return 0;

}

В этой программе процессы делятся на две группы: первая состоит из одного процесса (процесс с максимальным рангом в исходном коммуникаторе MPI_Comm_world), это — "сервер", а во вторую входят все остальные процессы. Между этими группами и создается интеркоммуникатор intercomm. Процессы-клиенты передают серверу сообщения. Сервер принимает эти сообщения с помощью подпрограммы стандартного блокирующего двухточечного приема и выводит их на экран. "Ненужные" коммуникаторы удаляются. Распечатка вывода этой программы выглядит следующим образом:

mpiexec –host -machinefile -n 10 – myprogr

Process rank 4 send 4

Process rank 8 send 8

Process rank 2 send 2

Process rank 6 send 6

Process rank 3 send 3

Process rank 1 send 1

Process rank 9 received 0 from 0

Process rank 9 received 1 from 1

Process rank 9 received 2 from 2

Process rank 9 received 3 from 3

Process rank 9 received 4 from 4

Process rank 9 received 5 from 5

Process rank 9 received 6 from 6

Process rank 9 received 7 from 7

Process rank 9 received 8 from 8

Process rank 5 send 5

Process rank 7 send 7

Process rank 0 send 0

Разберите работу программы и прокомментируйте результат ее выполнения.

5.4  Вопросы и задания для самоконтроля

1.  Какие фактические параметры и в каком порядке необходимо перечислять в списке параметров процедур двухточечного обмена?

2.  Перечислите множество вариантов посылки сообщений от одного процесса к другому в процедуре двухточечного обмена.