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)
#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 Все права принадлежат авторам размещенных материалов.
|