1

MPI には、 や などの非ブロッキング呼び出しがMPI_IsendありMPI_Irecvます。

私が p2p プロジェクトに取り組んでいる場合、サーバーは多くのクライアントをリッスンします。

それを行う1つの方法:

for(int i = 1; i < highest_rank; i++){
    MPI_Irecv(....,i,....statuses[i]); //listening to all slaves
}
while(true){
   for( int i = 1; i < highest_rank; i++){
         checkStatus(statuses[i])
         if true do somthing
}

私ができる別の古い方法は次のとおりです。

Server creating many POSIX threads, pass in a function, 
that function will call MPI_Recv and loop forever.

理論的には、サーバー側でより高速に実行できるのはどれですか? サーバーを書くための別のより良い方法があれば、私にも知らせてください。

4

3 に答える 3

3

後者のソリューションは、MPI プロセス内で pthread を管理することによるすべてのオーバーヘッドのため、あまり効率的ではないように思えます。

とにかく、MPI コードを次のように書き直します。

for(int i = 1; i < highest_rank; i++){
   MPI_Irev(....,i,....requests[i]); //listening to all slaves
}
while(true){
   MPI_waitany(highest_rank, request[i], index, status);
   //do something useful

}

MPI_Recv を MPI_ANY_SOURCE と共にメッセージの送信元のランクとして使用することもできます。サーバーはリクエストを処理する以外に何もする必要がないように思われるため、非同期 recv を使用する必要はありません。コードは次のとおりです。

while(true){
    MPI_Recv(... ,MPI_ANY_SOURCE, REQUEST_TAG,MPI_comm,status)
    //retrieve client id from status and do something
}
于 2013-02-09T23:06:24.853 に答える
1

MPI_Irecvを呼び出す場合、MPI_Test*またはMPI_Wait*が呼び出されて正常に完了するまで、recvバッファーをテストすることは安全ではありません。これらの呼び出しを行わずにバッファを直接テストする動作は、実装に依存します(そして、それほど悪くないものからセグメンテーション違反までの範囲です)。

リモートランクごとに1つのMPI_Irecvを使用して1:1マッピングを設定すると、機能するようになります。送信されるデータの量、および一度受信されたそのデータの寿命によっては、このアプローチは許容できない量のシステムリソースを消費する可能性があります。MPI_TestanyまたはMPI_Testallを使用すると、メッセージ処理とCPU負荷の最適なバランスが得られる可能性があります。着信メッセージの待機中に実行する必要のある非MPI処理がない場合は、MPI_WaitanyまたはMPI_Waitallの方が適している場合があります。

未処理のMPI_Irecv呼び出しがあるが、アプリケーションが通常の処理の終わりに達した場合、それらの未処理の呼び出しをMPI_Cancelすることが「必要」です。これを行わないと、MPI_Finalizeでエラーとして検出される可能性があります。

MPI_ANY_SOURCE上の単一のMPI_Irecv(または、メッセージ処理の必要性に応じてMPI_Recvのみ)も妥当なソリューションを提供します。このアプローチは、受信したデータの量が「大量」であり、処理後に安全に破棄できる場合にも役立ちます。一度に1つの着信バッファを処理すると、処理をシリアル化することを犠牲にして、必要なシステムリソースの合計を減らすことができます。

于 2013-02-10T05:01:50.270 に答える
0

POSIXスレッド(または他のスレッドメカニズムがあれば)を使用するというあなたのアイデアについてコメントさせてください。同時に複数のスレッドから MPI 呼び出しを行うには、MPI 実装が次の最高レベルのスレッド サポートで初期化されている必要がありますMPI_THREAD_MULTIPLE

int provided;

MPI_Init_thread(&argv, &argc, MPI_THREAD_MULTIPLE, &provided);
if (provided != MPI_THREAD_MULTIPLE)
{
    printf("Error: MPI does not provide full thread support!\n");
    MPI_Abort(MPI_COMM_WORLD, 1);
}

異なるスレッドからの同時呼び出しをサポートするオプションはかなり前に MPI 標準に導入されましたが、完全に機能するマルチスレッド サポートを提供するのに苦労している MPI 実装がまだあります。MPI は、少なくとも理論上は移植可能なアプリケーションを作成することを目的としていますが、この場合、実際の生活は理論とは大きく異なります。たとえば、最も広く使用されているオープンソース MPI 実装の 1 つである Open MPI は、ネイティブの InfiniBand 通信をまだサポートしていません (InfiniBand は、現在ほとんどの HPC クラスターで使用されている非常に高速な低レイテンシ ファブリックです) MPI_THREAD_MULTIPLE。通常の Ethernet 上の TCP/IP や IP-over-InfiniBand などのトランスポートでは、はるかに遅く、待ち時間が長くなります。また、MPI 実装がサポートしていないスーパーコンピューター ベンダーもいくつかあります。MPI_THREAD_MULTIPLE多くの場合、ハードウェアの動作が原因です。

また、MPI_Recv(必要な場合) 適切なスレッドのキャンセルに問題を引き起こすブロッキング呼び出しです。すべてのスレッドが何らかの方法で無限ループから逃れるようにする必要があります。たとえば、各ワーカーに適切なタグを付けて終了メッセージを送信させるか、他のプロトコルを使用します。

于 2013-02-10T11:21:22.047 に答える