Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции_MPI_OpenMP.doc
Скачиваний:
4
Добавлен:
16.11.2019
Размер:
1.09 Mб
Скачать

3. Mpi_Comm_split(comm, color, key, newcomm)

IN comm коммуникатор (дескриптор)

IN color управление созданием подмножества (целое)

IN key управление назначением номеров целое)

OUT newcomm новый коммуникатор (дескриптор)

Эта функция делит группу, связанную с comm, на непересекающиеся подгруппы по одной для каждого значения color. Каждая подгруппа содержит все процессы одного цвета. В пределах каждой под группы процессы пронумерованы в порядке, определенном значением аргумента key, со связями, разделенными согласно их номеру в старой группе.

Для каждой подгруппы создается новый коммуникатор и возвращается в аргументе newcomm. Процесс может иметь значение цвета MPI_UNDEFINED, тогда переменная newcomm возвращает значение MPI_COMM_NULL. Это коллективная операция, но каждому процессу разрешается иметь различные значения для color и key.

Обращение к MPI_Comm_create (сomm, group, newcomm) эквивалентно обращению к MPI_Comm_split (comm, color, key, newcomm), где все члены group имеют color =0 и key = номеру в group, и все процессы, которые не являются членами group, имеют color = MPI_UNDEFINED.

Функция MPI_Comm_split допускает более общее разделение группы на одну или несколько подгрупп с необязательным переупорядочением. Этот запрос используют только интра-коммуникаторы. Значение color должно быть неотрицательно.

Деструкторы коммуникаторов

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

Виртуальая топология процессов. Конструктоы топологий.

Топология процессов

Топология – это логическая организация процессов в группе (внутри коммуникатора). Такую логическую организацию процессов имеет еще одно название - “виртуальная топология ”.

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

Общим видом топологии процессов является структура графа. Узлы такого графа представляют процессы, ребра соответствуют связям между процессами. Большая доля всех параллельных приложений использует топологию двумерных массивов. Эта структура полностью определяется количеством процессов по каждой координате (строки и столбцы). Координаты в декартовой системе нумеруются от 0. Например, соотношение между номером процесса в группе и координатами в решетке 2х2 для четырех процессов будет следующим:

coord (0,0): rank 0 сoord (0,1): rank 1

сoord (1,0): rank 2 сoord (1,1): rank 3

Конструктор декартовой топологии