Группы процессов и коммуникаторы
Операции обмена между группами процессов
Интеробмены
При выполнении интеробмена процессу-источнику сообщения указывается ранг адресата относительно удаленной группы, а процессу-получателю — ранг источника (также относительно удаленной по отношению к получателю группы).
Обмен выполняется между лидерами обеих групп. Предполагается, что в обеих группах есть, по крайней мере, по одному процессу, который может обмениваться сообщениями со своим партнером.
Интеробмен возможен, только если создан соответствующий интеркоммуникатор, а это можно сделать с помощью подпрограммы:
int MPI_Intercomm_create(MPI_Comm local_comm, int local_leader, MPI_Comm peer_comm,
int remote_leader, int tag, MPI_Comm *new_intercomm)
MPI_Intercomm_create(local_comm, local_leader, peer_comm,
remote_leader, tag, new_intercomm, ierr)
Входные параметры этой подпрограммы:
- local_comm - локальный интракоммуникатор;
- local_leader - ранг лидера в локальном коммуникаторе (обычно 0);
- peer_comm - удаленный коммуникатор;
- remote_leader - ранг лидера в удаленном коммуникаторе (обычно 0);
- tag - тег интеркоммуникатора, используемый лидерами обеих групп для обменов в контексте родительского коммуникатора.
Выходной параметр - интеркоммуникатор (new_intercomm).
Вызов этой подпрограммы должен выполняться в обеих группах процессов, которые должны быть связаны между собой. В каждом из этих вызовов используется локальный интракоммуникатор, соответствующий данной группе процессов.
При работе с MPI_Intercomm_create локальная и удаленная группы процессов не должны пересекаться, иначе возможны "тупики".
Пример
#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, 1, MPI_INT, 0, 0, inter_comm);
printf("Process rank %i send %i\n", myid, counter);
}
MPI_Comm_free(&inter_comm );
MPI_Finalize();
}
В примере процессы делятся на две группы: первая состоит из одного процесса (процесс с максимальным рангом в исходном коммуникаторе MPI_COMM_WORLD), это - "сервер", а во вторую входят все остальные процессы.
Между этими группами создается интеркоммуникатор inter_comm.
Процессы-клиенты передают серверу сообщения.
Сервер принимает эти сообщения с помощью подпрограммы стандартного блокирующего двухточечного приема и выводит их на экран.
"Ненужные" коммуникаторы удаляются.