Здавалка
Главная | Обратная связь

MPI_Comm_free(comm)



INOUT commудаляемый коммуникатор (handle)

int MPI_Comm_free(MPI_Comm *comm)

 

Эта коллективная операция маркирует коммуникационный объект для удаления. Дескриптор устанавливается в MPI_COMM_NULL. Любые ждущие операции, которые используют этот коммуникатор, будут завершаться нормально; объект фактически удаляется только в том случае, если не имеется никаких других активных ссылок на него, т.е. не выполняется ни одна MPI функция с участием этого коммуникатора.

 

Ниже приведен пример создания двух групп и коммуникаторов для каждой группы. В группе созданных коммуникаторов выполнена функция инициализации номера процесса с выводом результата на экран.

 

#include <mpi.h>

#include <iostream.h>

 

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

{

int proc1, proc2;

MPI_Group grp_world, grp1, grp2;

MPI_Comm comm1=NULL, comm2=NULL;

 

int ranks1[ ] = {0,2};

int ranks2[ ] = {1,3};

 

MPI_Init( &argc, &argv);

 

MPI_Comm_group(MPI_COMM_WORLD,&grp_world);

 

MPI_Group_incl(grp_world, 2, ranks1, &grp1);

MPI_Comm_create(MPI_COMM_WORLD, grp1, &comm1);

 

MPI_Group_incl(grp_world, 2, ranks2, &grp2);

MPI_Comm_create(MPI_COMM_WORLD, grp2, &comm2);

 

if(comm1!=NULL) {

MPI_Comm_rank(comm1, &proc1);

cout<<"proc1="<<proc1<<endl;

}

if(comm2!=NULL) {

MPI_Comm_rank(comm2, &proc2);

cout<<"proc2="<<proc2<<endl;

}

MPI_Finalize();

return 0;

}

ПримерСледующий отрезок программы неверен.

switch(rank) {

case 0:

MPI_Bcast(buf1, count, type, 0, comm);

MPI_Bcast(buf2, count, type, 1, comm);

break;

case 1:

MPI_Bcast(buf2, count, type, 1, comm);

MPI_Bcast(buf1, count, type, 0, comm);

break;

}

Предполагается, что группа commесть {0,1}. Два процесса выполняют две операции широковещания в обратном порядке. Если операция синхронизирующая, произойдёт взаимоблокировка процессов. Коллективные операции должны быть выполнены в одинаковом порядке во всех элементах группы.

ПримерСледующий отрезок программы неверен.

switch(rank) {

case 0:

MPI_Bcast(buf1, count, type, 0, comm0);

MPI_Bcast(buf2, count, type, 2, comm2);

break;

case 1:

MPI_Bcast(buf1, count, type, 1, comm1);

MPI_Bcast(buf2, count, type, 0, comm0);

break;

case 2:

MPI_Bcast(buf1, count, type, 2, comm2);

MPI_Bcast(buf2, count, type, 1, comm1);

break;

}

Предположим, что группа из comm0есть {0,1},группа из comm1 –{1, 2}и группа из comm2 – {2,0}.Если операция широковещания синхронизирующая, то имеется циклическая зависимость: широковещание в comm2завершается только после широковещания в comm0;

широковещание в comm0завершается только после широковещания в comm1; и широковещание в comm1завершится только после широковещания в comm2.

Таким образом, будет иметь место взаимоблокировка процессов. Коллективные операции должны быть выполнены в таком порядке, чтобы не было циклических зависимостей.

 

ПримерСледующий отрезок программы неверен.

switch(rank) {

case 0:

MPI_Bcast(buf1, count, type, 0, comm);

MPI_Send(buf2, count, type, 1, tag, comm);

break;

case 1:

MPI_Recv(buf2, count, type, 0, tag, comm, status);

MPI_Bcast(buf1, count, type, 0, comm);

break;

}

Процесс с номером 0 выполняет широковещательную рассылку (bcast), сопровождаемую блокирующей посылкой данных (send).

Процесс с номером 1 выполняет блокирующий приём (receive), который соответствует посылке с последующей широковещательной передачей, соответствующей широковещательной операции процесса с номером 0. Такая программа может вызвать дедлок. Операция широковещания на процессе с номером 0 может вызвать блокирование, пока процесс с номером 1 не выполнит соответствующую широковещательную операцию, так что посылка не будет выполняться. Процесс 0 будет неопределенно долго блокироваться на приеме, в этом случае никогда не выполнится операция широковещания. Относительный порядок выполнения коллективных операций и операций парного обмена должен быть такой, чтобы даже в случае синхронизации не было взаимоблокировки процессов.

 

Интеркоммуникаторы

Конструктор интеркоммуникатора – функция MPI_Intercomm_create.Она создаст интеркоммуникатор из существующих интракоммуникаторов если как минимум один выбранный член из одной группы ("лидер группы") имеет возможность связываться с выбранным членом другой группы; т.е. существует "парный" коммуникатор, в котором находятся оба лидера, и каждый лидер знает ранг другого лидера, в этом парном коммуникаторе (два лидера могут быть одним и тем же процессом). Кроме того, члены каждой группы знают ранг своих лидеров.

Т.е. для того, чтобы создать интеркоммуникатор любые 2 процесса по одному из каждой группы должны иметь общий коммуникатор. Чаще всего на начальном этапе в качестве такого посредника используют MPI_COMM_WORLD.

 

Создание одного интеркоммуникатора из двух интракоммуникаторов является групповой операцией в связываемых группах. Далее, после создания интер-коммуникатора, по нему можно выполнять двухточечные обмены данными.

MPI_Intercomm_create (local_comm, local_leader, peer_comm, remote_leader, tag, newintercomm)

IN local_comm локальный интра-коммуникатор (handle)
IN local_leader ранг локального процесса (лидера) группы в local_comm (integer)
IN peer_comm интра-коммуникатор, который является посредником
IN remote_leader ранг удаленного процесса (лидера) группы в peer_comm;
IN tag тэг "безопасности" (integer)
OUT newintercomm новый интер-коммуникатор (handle)

 

#include <mpi.h>

#include <iostream.h>

 

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

int proc, proc1, proc2, proc3;

MPI_Group grp_world, grp1, grp2, grp3;

MPI_Comm comm1=NULL, comm2=NULL, comm3=NULL; /* интра-коммуникаторы */

MPI_Comm FirstComm, SecondComm; /* интер-коммуникаторы */

MPI_Status stat;

 

int ranks1[ ] = {0,2}; int ranks2[ ] = {1,3}; int ranks3[ ] = {4,5};

 

MPI_Init( &argc, &argv);

 

MPI_Comm_rank(MPI_COMM_WORLD, &proc);

MPI_Comm_group(MPI_COMM_WORLD,&grp_world);

 

MPI_Group_incl(grp_world, 2, ranks1, &grp1);

MPI_Comm_create(MPI_COMM_WORLD, grp1, &comm1);

 

MPI_Group_incl(grp_world, 2, ranks2, &grp2);

MPI_Comm_create(MPI_COMM_WORLD, grp2, &comm2);

 

MPI_Group_incl(grp_world, 2, ranks3, &grp3);

MPI_Comm_create(MPI_COMM_WORLD, grp3, &comm3);

 

if(comm1!=NULL){

MPI_Comm_rank(comm1, &proc1);

MPI_Intercomm_create(comm1, 0, MPI_COMM_WORLD, 4, 1, &FirstComm);

MPI_Intercomm_create(comm1, 0, MPI_COMM_WORLD, 1, 2, &SecondComm);

if(proc1==0) {

int a[10]={1,2,3,4,5,6,7,8,9,10};

MPI_Send(a,10,MPI_INT,0,99,FirstComm);

MPI_Send(a,10,MPI_INT,0,99,SecondComm);

}

}

if(comm2!=NULL){

MPI_Comm_rank(comm2, &proc2);

MPI_Intercomm_create(comm2, 0, MPI_COMM_WORLD, 0, 2, &SecondComm);

if(proc2==0){

int b[10];

MPI_Recv(b,10,MPI_INT,0,99,SecondComm,&stat);

for(int i=0; i<10; i++) cout<<b[i]<<endl;

}

}

if(comm3!=NULL){

MPI_Comm_rank(comm3, &proc3);

MPI_Intercomm_create(comm3, 0, MPI_COMM_WORLD, 0, 1, &FirstComm);

if(proc3==0){

int b[10];

MPI_Recv(b,10,MPI_INT,0,99,FirstComm,&stat);

for(int i=0; i<10; i++) cout<<b[i]<<endl;

}

}

}

 

Лекция 7







©2015 arhivinfo.ru Все права принадлежат авторам размещенных материалов.