Лаборатория Параллельных информационных технологий НИВЦ МГУ
Опубликован: 22.04.2008 | Доступ: свободный | Студентов: 1177 / 413 | Оценка: 4.30 / 4.19 | Длительность: 08:05:00
Специальности: Программист
Лекция 5:

Группы и коммуникаторы

< Лекция 4 || Лекция 5: 12 || Лекция 6 >
Аннотация: В MPI существуют широкие возможности для операций над группами процессов и коммуникаторов. В каком случае могут быть применимы данные операции? Какие операции можно совершать над группами процессов, а какие над коммуникаторами? Об этом поговорим в этой лекции

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

Операции с группами процессов

Группа - это упорядоченное множество процессов. Каждому процессу в группе сопоставлено целое число - ранг или номер. MPI_GROUP_EMPTY -пустая группа, не содержащая ни одного процесса. MPI_GROUP_NULL - значение, используемое для ошибочной группы.

Новые группы можно создавать как на основе уже существующих групп, так и на основе коммуникаторов, но в операциях обмена могут использоваться только коммуникаторы. Базовая группа, из которой создаются все остальные группы процессов, связана с коммуникатором MPI_COMM_WORLD, В нее входят все процессы приложения. Операции над группами процессов являются локальными, в них вовлекается только вызвавший процедуру процесс, а выполнение не требует межпроцессного обмена данными. Любой процесс может производить операции над любыми группами, в том числе над такими, которые не содержат данный процесс. При операциях над группами может получиться пустая группа MPI_GROUP_EMPTY.

MPI_COMM_GROUP(COMM, GROUP, IERR) INTEGER COMM, GROUP, IERR

Получение группы GROUP, соответствующей коммуникатору сомм. В языке Си параметр GROUP имеет предопределенный тип MPi_Group. Поскольку изначально существует единственный нетривиальный коммуникатор MPI_COMM_WORLD, сначала нужно получить соответствующую ему группу процессов. Это можно сделать при помощи следующего вызова:

call MPI_COMM_GROUP(MPI_COMM_WORLD, group, ierr)
MPI_GROUP_INCL(GROUP, N, RANKS, NEWGROUP, IERR) INTEGER GROUP, 
  N, RANKS(*), NEWGROUP, IERR

Создание группы NEWGROUP из N процессов прежней группы GROUP с рангами RANKS (l),...,RANKS (N) , причем рангу RANKS (I) в старой группе соответствует ранг i-l в новой группе. При N=0 создается пустая группа MPI_GROUP_EMPTY. Возможно использование этой процедуры для задания нового порядка процессов в группе.

MPI_GROUP_EXCL(GROUP, N, RANKS, NEWGROUP, IERR) INTEGER GROUP,
 N, RANKS(*), NEWGROUP, IERR

Создание группы NEWGROUP ИЗ процессов группы GROUP, исключая процессы с рангами RANKS (1),...,RANKS (N) , причем порядок оставшихся процессов в новой группе соответствует порядку процессов в старой группе. При N=0 создается группа, идентичная старой группе.

В следующем примере создается две непересекающихся группы процессов groupl и group2 на основе процессов группы group. В каждую из создаваемых групп войдет примерно половина процессов прежней группы (при нечетном числе процессов в группу group2 войдет на один процесс больше). Порядок нумерации процессов во вновь создаваемых группах сохранится.

size1 = size/2 do i = 1, size1
ranks(i)  = i-1 enddo
call MPI_GROUP_INCL(group,  size1,  ranks, group1,  ierr) 
 call MPI_GROUP_EXCL(group,  size1,  ranks, group2,  ierr)

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

MPI_GROUP_INTERSECTION(GROUP1, GROUP2, NEWGROUP, IERR) 
 INTEGER GROUP1, GROUP2, NEWGROUP, IERR

Создание группы NEWGROUP из пересечения групп GROUP 1 и GROUP 2. Полученная группа содержит все процессы группы GROUP 1, входящие также в группу GROUP2 и упорядоченные, как в первой группе.

MPI_GROUP UNION(GROUP1, GROUP2, NEWGROUP, IERR) 
 INTEGER GROUP1, GROUP2, NEWGROUP, IERR

Создание группы NEWGROUP ИЗ объединения групп GROUP 1 и GROUP 2. Полученная группа содержит все процессы группы GROUP l в прежнем порядке, за которыми следуют процессы группы GROUP 2, не вошедшие в группу GROUP 1, также в прежнем порядке.

MPI_GROUP_DIFFERENCE(GROUP1, GROUP2, NEWGROUP, IERR) 
 INTEGER GROUP1, GROUP2, NEWGROUP, IERR

Создание группы NEWGROUP ИЗ разности групп GROUP 1 и GROUP 2. Полученная группа содержит все элементы группы GROUP 1, не входящие в группу GROUP 2 и упорядоченные, как в первой группе.

Например, пусть в группу grl входят процессы о, 1, 2, 4, 5, а в группу gr2 -процессы 0, 2, 3 (нумерация процессов задана в группе, соответствующей коммуникатору MPI_COMM_WORLD ). Тогда после вызовов

  • call MPI_GROUP_INTERSECTION(gr1, gr2, newgr1, ierr)
  • call MPI_GROUP_UNION(gr1, gr2, newgr2, ierr)
  • call MPI_GROUP_DIFFERENCE(gr1, gr2, newgr3, ierr)
  • в группу newgrl входят процессы 0, 2;
  • в группу newgr2 входят процессы 0, 1, 2, 4, 5, 3;
  • в группу newgr3 входят процессы 1, 4, 5.

Порядок нумерации процессов в полученных группах соответствует порядку их перечисления.

MPI_GROUP_SIZE(GROUP, SIZE, IERR) INTEGER GROUP, SIZE, IERR

Определение количества SIZE процессов в группе GROUP.

MPI_GROUP_RANK(GROUP, RANK, IERR) INTEGER GROUP, RANK, IERR

Определение номера процесса RANK В группе GROUP. ЕСЛИ вызвавший процесс не входит в группу GROUP, ТО возвращается значение MPI_UNDEFINED.

MPI_GROUP_TRANSLATE_RANKS(GROUP1, N, RANKS1, GROUP2, RANKS2, IERR)
INTEGER GROUP1, N, RANKS1(*), GROUP2, RANKS2(*), IERR

В массиве RANKS2 возвращаются ранги в группе GROUP2 процессов с рангами RANKS 1 в группе GROUP 1. Параметр N задает число процессов, для которых нужно определить ранги.

МРI_GROUP_COMPARE(GROUP1, GROUP2, RESULT, IERR) 
 INTEGER GROUP1, GROUP2, RESULT, IERR

Сравнение групп GROUP l и GROUP 2. Если группы GROUP l и GROUP 2 полностью совпадают, то в параметре RESULT возвращается значение MPI_IDENT. ЕСЛИ группы отличаются только рангами процессов, то возвращается значение MPI_SIMILAR. Иначе возвращается значение MPI_UNEQUAL.

МРI_GROUP_FREE(GROUP, IERR) INTEGER GROUP, IERR

Уничтожение группы GROUP. После выполнения процедуры переменная GROUP принимает значение MPI_GROUP_NULL. Если с этой группой к моменту вызова процедуры уже выполняется какая-то операция, то она будет завершена.

В следующем примере все процессы приложения разбиваются на две непересекающиеся примерно равные группы groupl и group2. При нечетном числе процессов в группе group2 может оказаться на один процесс больше, тогда последний процесс из данной группы не должен обмениваться данными ни с одним процессом из группы groupl. С помощью вызовов процедуры MPI_GROUP_TRANSLATE_RANKS каждый процесс находит процесс с тем же номером в другой группе и обменивается с ним сообщением через коммуникатор mpi_comm_world при помощи вызова процедуры mpi_sendrecv. В конце программы не нужные далее группы уничтожаются с помощью вызовов процедур MPI_GROUP_FREE.

program example16
include 'mpif.h'
integer ierr, rank, i, size, size1
integer a(4), b(4)
integer status(MPI_STATUS_SIZE)
integer group, group1, group2
integer ranks(128), rank1, rank2, rank3
call MPI_INIT(ierr)
call MPI_COMM_SIZE(MPI_COMM_WORLD, size, ierr)
call MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierr)
call MPI_COMM_GROUP(MPI_COMM_WORLD, group, ierr)
size1 = size/2
do i = 1, size1
ranks(i) = i-1 enddo
call MPI_GROUP_INCL(group, size1, ranks, group1, ierr) call MPI_GROUP_EXCL
 (group, size1, ranks, group2, ierr) call MPI_GROUP_RANK (group1, rank1, ierr)
   call MPI_GROUP_RANK(group2, rank2, ierr) if (rank1 .eq. MPI_UNDEFINED) then
if(rank2 .lt. size1) then
call MPI_GROUP_TRANSLATE_RANKS (group1, 1, rank2,
& group, гапкЗ, ierr)
else
гапкЗ = MPI_UNDEFINED
end if
else
call MPI_GROUP_TRANSLATE_RANKS(group2, 1, rank1,
& group, гапкЗ, ierr)
end if
a(1) = rank
a(2) = rank1
a(3) = rank2
a(4) = rank3
if (rank3 .ne. MPI UNDEFINED) then
call MPI_SENDRECV(a, 4, MPI_INTEGER, rank3, 1,
& b, 4, MPI_INTEGER, rank3, 1,
& MPI_COMM_WORLD, status, ierr)
end if
call MPI_GROUP_FREE(group, ierr)
call MPI_GROUP_FREE(group1, ierr)
call MPI_GROUP_FREE(group2, ierr)
print *, 'process ', rank, ' a=', a, ' b=', b
call MPI_FINALIZE(ierr)
end
Листинг 5.1.
< Лекция 4 || Лекция 5: 12 || Лекция 6 >