Презентацию к данной лекции Вы можете скачать здесь.
В MPI имеются средства создания и преобразования коммуникаторов, которые дают возможность программисту в дополнение к стандартным предопределенным объектам создавать свои собственные. Это позволяет использовать разнообразные схемы взаимодействия процессов.
Используя средства MPI, можно создать новый коммуникатор, содержащий, например, те же процессы, что и исходный, но с новым контекстом (новыми свойствами).
Каждому процессу в группе сопоставлен свой ранг. Операции с группами могут выполняться отдельно от операций с коммуникаторами, но в операциях обмена используются только коммуникаторы.
В MPI имеется специальная предопределенная MPI_GROUP_EMPTY.
Коммуникаторы бывают двух типов:
Интракоммуникатором является MPI_COMM_WORLD.
В MPI-программах чаще используются интракоммуникаторы.
Можно организовать обмены между двумя непересекающимися группами процессов.
Если параллельная программа состоит из нескольких параллельных модулей, удобно разрешить одному модулю обмениваться сообщениями с другим, используя для адресации локальные по отношению ко второму модулю ранги. Такой подход удобен, например, при программировании параллельных клиент-серверных приложений.
Интеробмены реализуются с помощью
В контексте, связанном с интеркоммуникатором, передача сообщения в локальной группе всегда сопровождается его приемом в удаленной группе -
Конструкторы интеркоммуникаторов являются блокирующими операциями, поэтому во избежание тупиковых ситуаций локальная и удаленная группа не должны пересекаться (они не должны содержать одинаковые процессы).
Созданию нового коммуникатора предшествует создание соответствующей группы процессов. Операции создания групп аналогичны математическим операциям над множествами:
Новую группу можно создать только из уже существующих групп. Базовая группа, из которой формируются все другие группы, связана с коммуникатором MPI_COMM_WORLD.
В подпрограммах создания групп, как правило, нельзя использовать пустой коммуникатор MPI_COMM_NULL.
Доступ к группе group, связанной с коммуникатором comm можно получить, обратившись к подпрограмме MPI_Comm_group:
int MPI_Comm_group(MPI_Comm comm, MPI_Group *group)
MPI_Comm_group(comm, group, ierr)
Ее выходным параметром является группа.
Для выполнения операций с группой к ней сначала необходимо получить доступ.
Подпрограмма MPI_Group_incl создает новую группу newgroup из n процессов, входящих в группу oldgroup. Ранги этих процессов содержатся в массиве ranks:
int MPI_Group_incl(MPI_Group oldgroup, int n, int *ranks, MPI_Group *newgroup)
MPI_Group_incl(oldgroup, n, ranks, newgroup, ierr)
В новую группу войдут процессы с рангами ranks[0], …, ranks[n — 1], причем рангу i в новой группе соответствует ранг ranks[i] в старой группе. При n = 0 создается пустая группа MPI_GROUP_EMPTY.
С помощью данной подпрограммы можно не только создать новую группу, но и изменить порядок процессов в старой группе.
Подпрограмма MPI_Group_excl создает группу newgroup, исключая из исходной группы (group) процессы с рангами ranks[0], …, ranks[n — 1]:
int MPI_Group_excl(MPI_Group oldgroup, int n, int *ranks, MPI_Group *newgroup)
MPI_Group_excl(oldgroup, n, ranks, newgroup, ierr)
При n = 0 новая группа тождественна старой.
Подпрограмма MPI_Group_range_incl создает группу newgroup из группы group, добавляя в нее n процессов, ранг которых указан в массиве ranks:
int MPI_Group_range_incl(MPI_Group oldgroup, int n, int ranks[][3], MPI_Group *newgroup)
MPI_Group_range_incl(oldgroup, n, ranks, newgroup, ierr)
Массив ranks состоит из целочисленных триплетов вида (первый_1, последний_1, шаг_1), …, (первый_n, последний_n, шаг_n). В новую группу войдут процессы с рангами (по первой группе) первый_1, первый_1 + шаг_1, ….
Подпрограмма MPI_Group_difference создает новую группу (newgroup) из разности двух групп (group1) и (group2):
int MPI_Group_difference(MPI_Group group1, MPI_Group group2, MPI_Group *newgroup)
MPI_Group_difference(group1, group2, newgroup, ierr)
Подпрограмма MPI_Group_intersection создает новую группу (newgroup) из пересечения групп group1 и group2:
int MPI_Group_intersection(MPI_Group group1, MPI_Group group2, MPI_Group *newgroup)
MPI_Group_intersection(group1, group2, newgroup, ierr)
Подпрограмма MPI_Group_union создает группу (newgroup), объединяя группы group1 и group2:
int MPI_Group_union(MPI_Group group1, MPI_Group group2, MPI_Group *newgroup)
MPI_Group_union(group1, group2, newgroup, ierr)
Имеются и другие подпрограммы-конструкторы новых групп.
Вызов подпрограммы MPI_Group_free уничтожает группу group:
int MPI_Group_free(MPI_Group *group)
MPI_Group_free(group, ierr)
Для определения количества процессов (size) в группе (group) используется подпрограмма MPI_Group_size:
int MPI_Group_size(MPI_Group group, int *size)
MPI_Group_size(group, size, ierr)
Подпрограмма MPI_Group_rank возвращает ранг (rank) процесса в группе group:
int MPI_Group_rank(MPI_Group group, int *rank)
MPI_Group_rank(group, rank, ierr)
Если процесс не входит в указанную группу, возвращается значение MPI_UNDEFINED.
Создание коммуникатора - коллективная операция и соответствующая подпрограмма должна вызываться всеми процессами коммуникатора. Подпрограмма MPI_Comm_dup дублирует уже существующий коммуникатор oldcomm:
int MPI_Comm_dup(MPI_Comm oldcomm, MPI_Comm *newcomm) MPI_Comm_dup(oldcomm, newcomm, ierr)
В результате вызова создается новый коммуникатор (newcomm) с той же группой процессов, с теми же атрибутами, но с другим контекстом.
Эта подпрограмма может применяться как к интра-, так и интеркоммуникаторам.
Подпрограмма MPI_Comm_create создает новый коммуникатор (newcomm) из подмножества процессов (group) другого коммуникатора (oldcomm):
int MPI_Comm_create(MPI_Comm oldcomm, MPI_Group group, MPI_Comm *newcomm) MPI_Comm_create(oldcomm, group, newcomm, ierr)
Вызов этой подпрограммы должны выполнить все процессы из старого коммуникатора, даже если они не входят в группу group, с одинаковыми аргументами.
Данная операция применяется только к интракоммуникаторам. Она позволяет выделять подмножества процессов со своими областями взаимодействия, если, например, требуется уменьшить "зернистость" параллельной программы. Побочным эффектом применения подпрограммы MPI_Comm_create является синхронизация процессов. Если, например, одновременно создаются несколько коммуникаторов, они должны создаваться в одной последовательности всеми процессами.
#include "mpi.h"
#include <stdio.h>
int main(int argc,char *argv[])
{
char message[24];
MPI_Group MPI_GROUP_WORLD;
MPI_Group group;
MPI_Comm fcomm;
int size, q, proc;
int* process_ranks;
int rank, rank_in_group;
MPI_Status status;
MPI_Init(argc, argv);
MPI_Comm_size(MPI_COMM_WORLD, size);
MPI_Comm_rank(MPI_COMM_WORLD, rank);
printf("New group contains processes:");
q = size — 1;
process_ranks = (int*) malloc(q*sizeof(int));
for (proc = 0; proc < q; proc++)
{
process_ranks[proc] = proc;
printf("%i ", process_ranks[proc]);
}
printf("\n");
MPI_Comm_group(MPI_COMM_WORLD, MPI_GROUP_WORLD);
MPI_Group_incl(MPI_GROUP_WORLD, q, process_ranks, group);
MPI_Comm_create(MPI_COMM_WORLD, group, fcomm);
if (fcomm != MPI_COMM_NULL) {
MPI_Comm_group(fcomm, group);
MPI_Comm_rank(fcomm, rank_in_group);
if (rank_in_group == 0) {
strcpy(message, "Hi, Parallel Programmer!");
MPI_Bcast(message, 25, MPI_BYTE, 0, fcomm);
printf("0 send: %s\n", message);
}
else
{
MPI_Bcast(message, 25, MPI_BYTE, 0, fcomm);
printf("%i received: %s\n", rank_in_group, message);
}
MPI_Comm_free(fcomm);
MPI_Group_free(group);
}
MPI_Finalize();
return 0;
}
В следующем примере процессы разбиваются на две группы. Одна содержит процессы с чётными рангами, а другая – с нечётными.
#include "stdio.h"
#include "mpi.h"
void main(int argc, char *argv[])
{
int num, p;
int Neven, Nodd, members[6], even_rank, odd_rank;
MPI_Group group_world, even_group, odd_group;
MPI_Init(argc, argv);
MPI_Comm_rank(MPI_COMM_WORLD, num);
MPI_Comm_size(MPI_COMM_WORLD, p);
Neven = (p + 1)/2;
Nodd = p - Neven;
members[0] = 2;
members[1] = 0;
members[2] = 4;
MPI_Comm_group(MPI_COMM_WORLD, group_world);
MPI_Group_incl(group_world, Neven, members, even_group);
MPI_Group_excl(group_world, Neven, members, odd_group);
MPI_Barrier(MPI_COMM_WORLD);
if(num == 0) {
printf("Number of processes is %d\n", p);
printf("Number of odd processes is %d\n", Nodd);
printf("Number of even processes is %d\n", Neven);
printf("members[0] is assigned rank %d\n", members[0]);
printf("members[1] is assigned rank %d\n", members[1]);
printf("members[2] is assigned rank %d\n", members[2]);
printf("\n");
printf(" num even odd\n");
}
MPI_Barrier(MPI_COMM_WORLD);
MPI_Group_rank(even_group, even_rank);
MPI_Group_rank( odd_group, odd_rank);
printf("%8d %8d %8d\n",num, even_rank, odd_rank);
MPI_Finalize();
}
Подпрограмма MPI_Comm_free помечает коммуникатор comm для удаления:
int MPI_Comm_free(MPI_Comm *comm)
MPI_Comm_free(comm, ierr)
Обмены, связанные с этим коммуникатором, завершаются обычным образом, а сам коммуникатор удаляется только после того, как на него не будет активных ссылок. Данная операция может применяться к коммуникаторам обоих видов (интра- и интер-).
К числу операций управления коммуникаторами можно отнести операции MPI_Comm_size и MPI_Comm_rank. Они позволяют, в частности, распределить роли между процессами в модели master-slave.
При выполнении интеробмена процессу-источнику сообщения указывается ранг адресата относительно удаленной группы, а процессу-получателю — ранг источника (также относительно удаленной по отношению к получателю группы).
Обмен выполняется между лидерами обеих групп. Предполагается, что в обеих группах есть, по крайней мере, по одному процессу, который может обмениваться сообщениями со своим партнером.
Интеробмен возможен, только если создан соответствующий интеркоммуникатор, а это можно сделать с помощью подпрограммы:
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.
Процессы-клиенты передают серверу сообщения.
Сервер принимает эти сообщения с помощью подпрограммы стандартного блокирующего двухточечного приема и выводит их на экран.
"Ненужные" коммуникаторы удаляются.
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.