MPI_BCAST() применяется только к части базовой группы

Я сгруппировал 8 процессоров в две группы, в каждой из которых ровно по четыре процессора. Я прошу корень каждой подгруппы пообщаться со своими подчиненными с помощью подпрограммы «MPI_BCAST».

Я столкнулся с вопросом: чтобы указать корень подгруппы, должен ли я использовать исходный ранг, которому корень подгруппы соответствует с коммуникатором MPI_COMM_WORLD, или новый ранг, который он представляет с новым коммуникатором?

Возьмем, к примеру, приведенный ниже фрагмент кода: я хочу, чтобы P:0 отправлял данные своим подчиненным P:1, P:2 и P:3, и аналогичным образом я прошу P:4 отправлять свои данные P: 5, П:6, П:7. Чтобы достичь этой цели, мне интересно, следует ли мне указать четвертый аргумент в строке 36 как 1 или указать их как 0 и 4 соответственно в зависимости от того, на какую главу подгруппы я ссылаюсь?

Спасибо. Ли

1  program main
2    include 'mpif.h'
3    integer :: ierr, irank, num_procs, base_group
4    integer :: nrow, ncol, irow, icol
5    integer :: dummy_group, dummy_comm, new_comm, new_rank
6    integer :: i, j, roster(4), data(4)
7    
8    call MPI_Init ( ierr )
9    call MPI_COMM_RANK( MPI_comm_world, irank, ierr )
10   call MPI_COMM_SIZE( MPI_comm_world, num_procs, ierr)
11   call MPI_COMM_GROUP( MPI_comm_world, base_group, ierr)
12   nrow = 4
13   ncol = 2
14   irow = mod( irank, nrow )  + 1
15   icol = irank/nrow + 1
16   
17   roster(1) = 0
18   do i = 2, nrow
19       roster(i) = roster(i-1) + 1        
20   enddo
21   
22   do i = 1, ncol
23    call MPI_GROUP_INCL( base_group, nrow, roster, dummy_group, ierr )
24    call MPI_COMM_CREATE( MPI_COMM_WORLD, dummy_group, dummy_comm, ierr ) 
25    if( icol == i ) new_comm = dummy_comm
26    forall( j=1:nrow ) roster(j) = roster(j) + nrow
27   enddo
28   
29   ! Here I want to initialize data for processors P:0 and P:4
30   if( irank == 0 ) data = 0
31   if( irank == 4 ) data = 4
32   
33   ! In the code below I want to require P:0 to send data to 
34   ! its subordinates P:1, P:2, and P:3. Similarly, I ask P:4 
35   ! to send out its data to P:5, P:6, P:7.
36   call MPI_BCAST( data, 4, MPI_INTEGER, 0, new_comm, ierr)
37   
38   call MPI_Finalize ( ierr ) 
39 end program

person Li-Pin Juan    schedule 29.05.2014    source источник


Ответы (1)


Все аргументы рангового типа (источник, цель и т. д.) в MPI должны быть рангами в том же коммуникаторе, что и аргумент коммуникатора. На практике это означает, что после создания нового коммуникатора каждый процесс в этом коммуникаторе должен вызывать MPI_Comm_rank и MPI_Comm_size для получения своего ранга и общего размера в этом коммуникаторе (если только вы не можете вывести новый ранг и размер другими способами в вашем коде, конечно).

Кроме того, поскольку то, что вы делаете, - это разделение исходного коммуникатора на два непересекающихся коммуникатора, я думаю, что более простой способ добиться этого - использовать MPI_Comm_split, а не настраивать группы вручную, как вы это сделали.

person janneb    schedule 29.05.2014
comment
Спасибо за ответ. Вместо использования MPI_Comm_split я решил использовать этот альтернативный подход из-за неравномерного разделения процессоров в моей реальной программе. После проб и ошибок я, наконец, получил то, что хотел, задав четвертому аргументу в строке 36 значение 0, что означает, что протокол параллелизма автоматически назначает ранг каждого нового корня подгруппы равным 0, а не 1 (что является ошибкой) или 0. и 4 (спецификация, которая не соответствует тому, как работает протокол). - person Li-Pin Juan; 29.05.2014
comment
Можно также использовать непонятную MPI_Group_translate_ranks для преобразования ранга процесса в исходной группе в ранг, который он имеет в новой группе. Полезно, когда кто-то разделяет коммуникатор и не знает, какова новая нумерация рангов, например. если один и тот же ключ был предоставлен всеми рангами для разделенного вызова. - person Hristo Iliev; 29.05.2014