Подтвердить что ты не робот

Разница между функциями MPI_Allgather и MPI_Alltoall?

В чем основное отличие между функциями MPI_Allgather и MPI_Alltoall в MPI?

Я имею в виду, может ли кто-нибудь дать мне примеры, когда MPI_Allgather будет полезен, а MPI_Alltoall не будет? и наоборот.

Я не могу понять основное различие? Похоже, что в обоих случаях все процессы отправляют элементы send_cnt всем другим процессам, участвующим в коммуникаторе, и получают их?

Спасибо

4b9b3361

Ответ 1

В картине написано более тысячи слов, так что вот несколько художественных фотографий ASCII:

rank    send buf                        recv buf
----    --------                        --------
 0      a,b,c         MPI_Allgather     a,b,c,A,B,C,#,@,%
 1      A,B,C        ---------------->  a,b,c,A,B,C,#,@,%
 2      #,@,%                           a,b,c,A,B,C,#,@,%

Это обычный регулярный MPI_Gather, только в этом случае все процессы получают куски данных, т.е. операция не имеет значения root.

rank    send buf                        recv buf
----    --------                        --------
 0      a,b,c          MPI_Alltoall     a,A,#
 1      A,B,C        ---------------->  b,B,@
 2      #,@,%                           c,C,%

(a more elaborate case with two elements per process)

rank    send buf                        recv buf
----    --------                        --------
 0      a,b,c,d,e,f    MPI_Alltoall     a,b,A,B,#,@
 1      A,B,C,D,E,F  ---------------->  c,d,C,D,%,$
 2      #,@,%,$,&,*                     e,f,E,F,&,*

(выглядит лучше, если каждый элемент окрашен раном, который отправляет его, но...)

MPI_Alltoall работает как объединенный MPI_Scatter и MPI_Gather - буфер отправки в каждом процессе разбивается как на MPI_Scatter, а затем каждый столбец кусков собирается соответствующим процессом, чей ранг соответствует числу кусок колонка. MPI_Alltoall также можно рассматривать как глобальную операцию транспонирования, действующую на куски данных.

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

operation      send buf size      recv buf size
---------      -------------      -------------
MPI_Allgather  sendcnt            n_procs * sendcnt
MPI_Alltoall   n_procs * sendcnt  n_procs * sendcnt

Размер буфера приема на самом деле n_procs * recvcnt, но MPI указывает, что количество отправленных базовых элементов должно быть равно количеству принятых базовых элементов, следовательно, если один и тот же тип данных MPI используется в обеих частях отправки и получения MPI_All..., то recvcnt должен быть равен sendcnt.

Сразу видно, что при одном и том же размере полученных данных количество данных, отправляемых каждым процессом, отличается. Для того чтобы обе операции были равны, одним из необходимых условий является то, что размеры отправленных буферов в обоих случаях равны, т.е. n_procs * sendcnt == sendcnt, что возможно только в том случае, если n_procs == 1, т.е. если есть только один процесс или если sendcnt == 0, т.е. никакие данные не отправляются вообще. Следовательно, практически нет практического случая, когда обе операции действительно взаимозаменяемы. Но можно моделировать MPI_Allgather с помощью MPI_Alltoall, повторяя n_procs раза те же данные в буфере отправки (как уже было отмечено Тайлером Гиллом). Вот действие MPI_Allgather с одноэлементными буферами отправки:

rank    send buf                        recv buf
----    --------                        --------
 0      a             MPI_Allgather     a,A,#
 1      A            ---------------->  a,A,#
 2      #                               a,A,#

И здесь то же самое реализовано с MPI_Alltoall:

rank    send buf                        recv buf
----    --------                        --------
 0      a,a,a          MPI_Alltoall     a,A,#
 1      A,A,A        ---------------->  a,A,#
 2      #,#,#                           a,A,#

Реверс невозможен - в общем случае нельзя моделировать действие MPI_Alltoall с MPI_Allgather.

Ответ 2

Эти два скриншота имеют быстрое объяснение:

MPI_Allgatherv

MPI_Allgatherv

MPI_Alltoallv

MPI_Alltoallv

Хотя это сравнение между MPI_Allgatherv и MPI_Alltoallv, но также объясняет, как MPI_Allgather отличается от MPI_Alltoall.

Ответ 3

Несмотря на то, что эти два метода действительно очень похожи, существует, по-видимому, одно существенное различие между ними.

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

MPI_Alltoall не передает одинаковые значения друг другу. Вместо того, чтобы предоставлять одно значение, которое должно использоваться совместно друг с другом, каждый процесс указывает одно значение, которое нужно передать друг другу. Другими словами, с n процессами каждый должен указать n значений для совместного использования. Затем для каждого процессора j его k'th значение будет отправлено для обработки k j'th индекса в буфере приема. Это полезно, если каждый процесс имеет единственное уникальное сообщение для каждого другого процесса.

В качестве окончательной заметки результаты работы allgather и alltoall будут одинаковыми в том случае, когда каждый процесс заполняет буфер отправки одинаковым значением. Единственное различие заключалось бы в том, что allgather, вероятно, будет намного более эффективным.