web-dev-qa-db-ja.com

MPI_Allgather関数とMPI_Alltoall関数の違いは何ですか?

MPIのMPI_Allgather関数とMPI_Alltoall関数の主な違いは何ですか?

つまり、MPI_Allgatherが役立ち、MPI_Alltoallが役に立たない例を誰かが私に与えることができるということですか?およびその逆。

主な違いが理解できませんか?どちらの場合も、すべてのプロセスがコミュニケーターに参加している他のすべてのプロセスにsend_cnt要素を送信して受信するように見えますか?

ありがとうございました

24
Kranthi Kumar

画像には1000を超える単語が含まれているため、ここにいくつかの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であり、この場合にのみ、すべてのプロセスがデータチャンクを受信します。つまり、操作にはルートがありません。

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_AlltoallMPI_ScatterMPI_Gatherの組み合わせとして機能します-各プロセスの送信バッファはMPI_Scatterのように分割され、チャンクの各列はそれぞれのプロセスによってランク付けされます。チャンク列の番号と一致します。 MPI_Alltoallは、データのチャンクに作用するグローバル転置操作と見なすこともできます。

2つの操作を交換できる場合はありますか?この質問に適切に回答するには、送信バッファ内のデータと受信バッファ内のデータのサイズを分析する必要があります。

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...の送信部分と受信部分の両方で使用され、recvcntsendcntと等しくなければなりません。

同じサイズの受信データに対して、各プロセスによって送信されるデータの量が異なることはすぐにわかります。 2つの操作が等しい場合、1つの必要条件は、両方のケースで送信されたバッファーのサイズが等しい、つまりn_procs * sendcnt == sendcntであるということです。これは、n_procs == 1、つまりプロセスが1つしかない場合にのみ可能です。 、またはsendcnt == 0の場合、つまりデータがまったく送信されていません。したがって、両方の操作が実際に交換可能であるという実際的に実行可能なケースはありません。しかし、送信バッファ内の同じデータをMPI_Allgather倍に繰り返すことにより、MPI_Alltoalln_procsでシミュレートできます(すでにTyler Gillによって指摘されています)。次に、1つの要素の送信バッファを使用した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_AlltoallMPI_Allgatherでシミュレートすることはできません。

69
Hristo Iliev

これらの2つのスクリーンショットは簡単な説明です。

MPI_Allgatherv

MPI_Allgatherv

MPI_Alltoallv

MPI_Alltoallv

これはMPI_AllgathervとMPI_Alltoallvの比較ですが、MPI_AllgatherとMPI_Alltoallの違いについても説明しています。

13
Tong Zhou

これらの2つの方法は確かに非常に似ていますが、2つの方法の間に1つの重要な違いがあるようです。

MPI_Allgatherは、各プロセスの受信バッファーにまったく同じデータがあることで終了し、各プロセスは配列全体に1つの値を提供します。たとえば、一連のプロセスのそれぞれが状態に関する単一の値を他のすべての人と共有する必要がある場合、それぞれが単一の値を提供します。これらの値はすべてのユーザーに送信されるため、すべてのユーザーが同じ構造のコピーを持つことになります。

MPI_Alltoallは、他のプロセスに同じ値を送信しません。他のプロセスと共有する必要がある単一の値を提供する代わりに、各プロセスは、他のプロセスに与える1つの値を指定します。つまり、n個のプロセスでは、それぞれが共有するn個の値を指定する必要があります。次に、各プロセッサーjについて、そのk番目の値が送信され、受信バッファー内のk番目のj番目のインデックスを処理します。これは、各プロセスに他のプロセスごとに1つの一意のメッセージがある場合に役立ちます。

最後に、allgatherとalltoallを実行した結果は、各プロセスが送信バッファーを同じ値で満たした場合と同じになります。唯一の違いは、オールギャザーの方がはるかに効率的であることです。

4
Tyler Gill