Вперед: 4.7. Топология процессов
Назад: 4.6.2. Функции работы с группами
К содержанию: Оглавление


4.6.3. Функции работы с коммуникаторами

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

Две основных функции доступа к коммуникатору, MPI_Comm_size - опрос числа процессов в области связи и MPI_Comm_rank - опрос идентификатора номера процесса в области связи, были рассмотрены в самом начале среди базовых функций MPI.

Кроме них, имеется функция сравнения двух коммуникаторов MPI_Comm_compare.

С:
MPI_Comm_compare(MPI_Comm comm1,MPI_Comm comm2, int *result)
FORTRAN:
MPI_COMM_COMPARE(COMM1, COMM2, RESULT, IERROR)
INTEGER COMM1, COMM2, RESULT, IERROR
IN comm1 - первый коммуникатор;
IN comm2 - второй коммуникатор;
OUT result - результат сравнения.

Возможные значения результата сравнения:
MPI_IDENT - коммуникаторы идентичны, представляют один и тот же объект;
MPI_CONGRUENT - коммуникаторы конгруэнтны, две области связи с одними и теми же атрибутами группы;
MPI_SIMILAR - коммуникаторы подобны, группы содержат одни и те же процессы, но другое упорядочивание;
MPI_UNEQUAL - во всех других случаях.

Создание нового коммуникатора возможно с помощью одной из трех функций: MPI_Comm_dup, MPI_Comm_create, MPI_Comm_split.

Функция дублирования коммуникатора MPI_Comm_dup

С:
MPI_Comm_dup(MPI_Comm comm, MPI_Comm *newcomm)
FORTRAN:
MPI_COMM_DUP(COMM, NEWCOMM, IERROR)
INTEGER COMM, NEWCOMM, IERROR
IN comm - коммуникатор;
OUT newcomm - копия коммуникатора.

Функция полезна для последующего создания коммуникаторов с новыми атрибутами.

Функция создания коммуникатора MPI_Comm_create

С:
MPI_Comm_create(MPI_Comm comm, MPI_Group group,
MPI_Comm *newcomm)
FORTRAN:
MPI_COMM_CREATE(COMM, GROUP, NEWCOMM, IERROR)
INTEGER COMM, GROUP, NEWCOMM, IERROR
IN comm - родительский коммуникатор;
IN group - группа, для которой создается коммуникатор;
OUT newcomm - новый коммуникатор.

Эта функция создает коммуникатор для группы group. Для процессов, которые не являются членами группы, возвращается значение MPI_COMM_NULL. Функция возвращает код ошибки, если группа group не является подгруппой родительского коммуникатора.

Функция расщепления коммуникатора MPI_Comm_split

С:
MPI_Comm_split(MPI_Comm comm, int color, int key,
MPI_Comm *newcomm)
FORTRAN:
MPI_COMM_SPLIT(COMM, COLOR, KEY, NEWCOMM, IERROR)
INTEGER COMM, COLOR, KEY, NEWCOMM, IERROR
IN comm - родительский коммуникатор;
IN color - признак подгруппы;
IN key - управление упорядочиванием;
OUT newcomm - новый коммуникатор.

Функция расщепляет группу, связанную с родительским коммуникатором, на непересекающиеся подгруппы по одной на каждое значение признака подгруппы color. Значение color должно быть неотрицательным. Каждая подгруппа содержит процессы с одним и тем же значением color. Параметр key управляет упорядочиванием внутри новых групп: меньшему значению key соответствует меньшее значение идентификатора процесса. В случае равенства параметра key для нескольких процессов упорядочивание выполняется в соответствии с порядком в родительской группе.

Приведем алгоритм расщепления группы из восьми процессов на три подгруппы и его графическую интерпретацию (Рис. 4.18).

MPI_comm comm, newcomm;
int myid, color;
 . . . . . .
MPI_Comm_rank(comm, &myid);
color = myid%3;
MPI_Comm_split(comm, color, myid, &newcomm);

Разбиение группы из восьми процессов на три подгруппы.

Рис. 4.18 Разбиение группы из восьми процессов на три подгруппы.

В данном примере первую подгруппу образовали процессы, номера которых делятся на 3 без остатка, вторую - для которых остаток равен 1 и третью - для которых остаток равен 2. Отметим, что после выполнения функции MPI_Comm_split значения коммуникатора newcomm в процессах разных подгрупп будут отличаться.

Функция уничтожения коммуникатораа MPI_Comm_free

С:
MPI_Comm_free(MPI_Comm *comm)
FORTRAN:
MPI_COMM_FREE(COMM, IERROR)
INTEGER COMM, IERROR
IN comm - уничтожаемый коммуникатор.

Примечание: За рамками данного руководства мы оставим обсуждение inter-коммуникаторов и вопросы, связанные с изменением или добавлением новых атрибутов коммуникаторов.

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

Программа group.c

#include "mpi.h"
 #include <stdio.h>
 #define NPROCS 8

 int main(argc,argv)
 int argc;
 char *argv[]; {
 int    rank, new_rank, sendbuf, recvbuf, numtasks,
      ranks1[4]={0,1,2,3}, ranks2[4]={4,5,6,7};
 MPI_Group orig_group, new_group;
 MPI_Comm  new_comm;

 MPI_Init(&argc,&argv);
 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
 MPI_Comm_size(MPI_COMM_WORLD, &numtasks);

 if (numtasks != NPROCS) {
 printf("Must specify MP_PROCS= %d. Terminating.\n",NPROCS);
 MPI_Finalize();
 exit(0);
 }
 sendbuf = rank;
 MPI_Comm_group(MPI_COMM_WORLD, &orig_group);

 if (rank < NPROCS/2) {
 MPI_Group_incl(orig_group, NPROCS/2, ranks1, &new_group);
 }
 else {
 MPI_Group_incl(orig_group, NPROCS/2, ranks2, &new_group);
 }
 MPI_Comm_create(MPI_COMM_WORLD, new_group, &new_comm);
MPI_Allreduce(&sendbuf,&recvbuf,1,MPI_INT,MPI_SUM,new_comm);
 MPI_Group_rank (new_group, &new_rank);   	printf("rank=%dnewrank=%drecvbuf=%d\n",
rank,new_rank,recvbuf);
 MPI_Finalize();
 }
 

Программа group.f

program group
   include 'mpif.h'
   integer NPROCS
   parameter(NPROCS=8)
   integer rank, new_rank, sendbuf, recvbuf, numtasks
   integer ranks1(4), ranks2(4), ierr
   integer orig_group, new_group, new_comm
   data ranks1 /0, 1, 2, 3/, ranks2 /4, 5, 6, 7/

   call MPI_INIT(ierr)
   call MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierr)
   call MPI_COMM_SIZE(MPI_COMM_WORLD, numtasks, ierr)

   if (numtasks .ne. NPROCS) then
   print *, 'Must specify MPROCS= ',NPROCS,'Terminating.'
   call MPI_FINALIZE(ierr)
   stop
   endif
   sendbuf = rank
   call MPI_COMM_GROUP(MPI_COMM_WORLD, orig_group, ierr)
   if (rank .lt. NPROCS/2) then
   call MPI_GROUP_INCL(orig_group, NPROCS/2, ranks1, 
   &         new_group, ierr)
   else 
   call MPI_GROUP_INCL(orig_group, NPROCS/2, ranks2, 
   &         new_group, ierr)
   endif
   call MPI_COMM_CREATE(MPI_COMM_WORLD, new_group, 
   &         new_comm, ierr)
   call MPI_ALLREDUCE(sendbuf, recvbuf, 1, MPI_INTEGER,
   &         MPI_SUM, new_comm, ierr)

   call MPI_GROUP_RANK(new_group, new_rank, ierr)
   print*, 'rank= ',rank,' newrank= ',new_rank,'recvbuf=',
   &   recvbuf

   call MPI_FINALIZE(ierr)
   end
 

Результат работы:

rank= 0 newrank= 0 recvbuf= 6
rank= 4 newrank= 0 recvbuf= 22
rank= 6 newrank= 2 recvbuf= 22
rank= 2 newrank= 2 recvbuf= 6
rank= 7 newrank= 3 recvbuf= 22
rank= 3 newrank= 3 recvbuf= 6
rank= 5 newrank= 1 recvbuf= 22
rank= 1 newrank= 1 recvbuf= 6
 


Вперед: 4.7. Топология процессов
Назад: 4.6.2. Функции работы с группами
К содержанию: Оглавление