2011-08-05 9 views
4

MPIでは、単に便宜のために関数MPI_Bcastを使用するか、すべてのランクをループしてすべてに同じメッセージを送信するのではなく、効率的な利点がありますか?MPI_Bcast:効率の優位性?

根拠:MPI_Bcast根本を含む誰にでもメッセージを送信する動作は私には不便なので、理由がないか、メッセージを送信しないようにすることはできませんルートに。

+0

なぜMPI_Bcastのルートに問題がありますか? –

答えて

7

MPI_Bcastを使用することは間違いなく独自のものを使用するより効率的です。メッセージサイズや通信アーキテクチャなどの要素に基づいて集団オペレーションを最適化するために、すべてのMPI実装で多くの作業が行われています。

たとえば、MPI_Bcast in MPICH2 would use a different algorithm depending on the size of the messageです。短いメッセージの場合、バイナリツリーを使用して処理の負荷とレイテンシを最小限に抑えます。長いメッセージの場合、それはバイナリツリーの散布に続いてallgatherとして実装されます。

さらに、HPCベンダーは、基本的なインターコネクトを効率的に使用するMPI実装を提供しています(特に、集合的な操作の場合)。例えば、hardware supported multicast schemeまたはuse bespoke algorithms that can take advantage of the existing interconnectsを使用することができます。

2

MPI_Bcastは、1つのプロセス( 'root')からすべてothersにメッセージを送信します。おそらく、すべてのプロセスをループするよりも少し速いでしょう。例えば、mpich2実装では、2項木を使用してメッセージを配信します。

あなたはMPI_COMM_WORLDにブロードキャストしたくない、しかし、あなたがサブグループを定義したい、あなたはこのようにそれについて行くことができた場合:

次のような出力を生成可能性がある
#include <stdio.h> 
#include "mpi.h" 

#define NPROCS 8 

int main(int argc, char **argv) 
{ 
    int rank, new_rank, sendbuf, recvbuf, 
    ranks1[4]={0,1,2,3}, ranks2[4]={4,5,6,7}; 

    MPI_Group orig_group, new_group; 
    MPI_Comm new_comm; 

    MPI_Init(&argc,&argv); 
    MPI_Comm_rank(MPI_COMM_WORLD, &rank); 
    sendbuf = rank; 

    /* Extract the original group handle */ 
    MPI_Comm_group(MPI_COMM_WORLD, &orig_group); 

    /* Divide tasks into two groups based on rank */ 
    if (rank < NPROCS/2) { 
     MPI_Group_incl(orig_group, NPROCS/2, ranks1, &new_group); 
    } else { 
     MPI_Group_incl(orig_group, NPROCS/2, ranks2, &new_group); 
    } 

    /* Create new communicator and then perform some comm 
    * Here, MPI_Allreduce, but you can MPI_Bcast at will 
    */ 
    MPI_Comm_create(MPI_COMM_WORLD, new_group, &new_comm); 
    MPI_Allreduce(&sendbuf, &recvbuf, 1, MPI_INT, MPI_SUM, new_comm); 
    MPI_Group_rank (new_group, &new_rank); 

    printf("rank= %d newrank= %d recvbuf= %d\n", rank, new_rank, recvbuf); 

    MPI_Finalize(); 
} 

rank= 7 newrank= 3 recvbuf= 22 
rank= 0 newrank= 0 recvbuf= 6 
rank= 1 newrank= 1 recvbuf= 6 
rank= 2 newrank= 2 recvbuf= 6 
rank= 6 newrank= 2 recvbuf= 22 
rank= 3 newrank= 3 recvbuf= 6 
rank= 4 newrank= 0 recvbuf= 22 
rank= 5 newrank= 1 recvbuf= 22 
3

一括通信は多くはとなります。 MPI implementのすべては、それらのルーチンを高速で処理するために多くの時間を費やします。

タスクのサブセットのみで集団型のものだけを日常的に実行したい場合は、独自のサブコミュニケータを作成し、それらのコミュニケータに対してBCASTなどを使用することをお勧めします。

+0

サブコミュニケータの使用についての良い点。 +1 –

+0

代替通信であっても、その通信のルートは引き続き一括操作に参加します。 OPは、具体的には、ルートを持つことがメッセージを得ることが問題であると述べた。 –

+1

メッセージを自身に送信するルートはnull操作であり、メモリコピーでもありません。 –

2

一般的なケースでは、MPI_Bcastがおそらくループより高速であると答えています。一般に、MPI集団は、広範囲のメッセージサイズ、通信サイズ、および特定のランクのレイアウトにわたって最適化されています。

しかし、特定のメッセージサイズ、通信サイズ、およびランクのレイアウトで集合を倒すことは可能かもしれません。例えば、非ブロッキングのポイントツーポイントコール(例えば、ISendおよびRecv/IRecv)上のループはより高速かもしれないが、たぶんいくつかの特定のメッセージサイズ、通信サイズ、およびランクレイアウトでのみ可能である。

コーディングする特定のアルゴリズムでBcastのパターンが必要な場合(たとえば、すべてのランクがルートから同じデータペイロードを取得する場合)、Bcast集合体を使用します。一般的に、あなた自身の「集合的な置換」を巻き込むことによって合併症を加える価値はありません。

アルゴリズムが必要とするいくつかのメッセージパターンと部分的な適合のみのBcastがある場合は、独自のローリングの価値があるかもしれませんが、個人的にはそのバーを高く設定します。

+0

私は同意します。 \t collectivesのパラメータを手動で調整する(手動でコマンドライン引数/環境変数を使用するか、mpitune for IntelMPIのようなものを介して自動的に行う)のが簡単で、独自のパフォーマンス集団を書き直すのは簡単です。 –

関連する問題