2016-10-25 5 views
1

前提: 多くのランクは、他のランクにデータを送信する必要があります。他のランクは )MPIで非ブロッキング通信によるメッセージ確認を確認

は、結果的に受信機は、彼らがどこから受け取るか、またはされますどのように多くのメッセージを知らない受信機に不明な総コミュニケーサイズ

2)の通常ごく一部です。

各ランクはバリア独自のIsendsが完了したときにすべてのランク上の送信メッセージは、「空気中」である場合、バリアが

終了に達したことで

Isend all messages 

Busy wait 
    Probe & Recv messages 
    When all Isends complete 
     start IBarrier 
    exit when IBarrier completes 

を次のように可能な解決策があります

問題: MPI 3.1標準のセクション3.7.3では、MPI_TestまたはMPI_Waitを使用した送信の完了が、対応する操作が完了したことを意味するのではなく、バッファを自由に再利用できることを示しています。

これは明らかに対応するIrecvがないハングするIsendが存在する競合状態になります。メッセージがIrecvと一致する前にIBarrierに達しているため、受信ランクはもはやリッスンしません。

+0

1つ(メッセージの完了を送信する)ともう1つ(受信を停止することを知っていること)は何ですか?最初のセクションでは、引用したセクションで説明したように、 'MPI_Issend'同期モードsendを使用することができます。第2の場合、(例えば、特別なタグによって示されるような)停止メッセージを送信する。 – Zulan

+0

ランク1ランクは、1)すべてのメッセージが特定のランクに送信されているかどうかを知っている2)メッセージがいくつあるか。 1つのランクからのすべてのメッセージが異なる宛先に送信された後で障壁に到達すると、これを適切に同期するように見えます。バリアが完了すると、すべてのランクのすべてのメッセージがそれぞれのrecv –

+0

MPI 3.2に到達しましたか?それは存在しますか?私が知っている最後のものは3.1ですが、多分私は何かを見逃しました...それを除いて、私はあなたの質問を理解していません。意味のあるコードスニペットを例に挙げてください。 – Gilles

答えて

1

あなたの問題を暴露する方法から、最初に同期の問題はないように見えます。したがって、ここで私が提案するソリューションです:あなたが見ることができるように

int sendSizes[size]; // size of the messages I'll send to each process 
// Populate sendSizes here 
/* ........ */ 

int recvSizes[size]; // size of the messages I'll receive from each process 
MPI_Alltoall(sendSizes, 1, MPI_INT, recvSizes, 1, MPI_INT, MPI_COMM_WORLD); 

// Now I know exactly what to expect from each process 
// I could use a Irecv - Isend - Waitall approach 
// but a MPI_Alltoallv might be more appropriated 
int sendDispls[size], recvDispls[size]; 
sendDispls[0] = recvDispls[0] = 0; 
for (int i = 0; i < size - 1; i++) { 
    sendDispls[i+1] = sendDispls[i] + sendSizes[i]; 
    recvDispls[i+1] = recvDispls[i] + recvSizes[i]; 
} 
int fullSendSize = sendDispls[size-1] + sendSizes[size-1]; 
double sendBuff[fullSendSize]; 
// Populate the sending buffer here 
/* ........ */ 

int fullRecvSize = recvDispls[size-1] + recvSizes[size-1]; 
double recvBuff[fullRecvSize]; 
MPI_Alltoallv(sendBuff, sendSizes, sendDispls, MPI_DOUBLE, 
       recvBuff, recvSizes, recvDispls, MPI_DOUBLE, 
       MPI_COMM_WORLD); 

は、ソリューションの礎石は、すべてのプロセスは、他のすべてのプロセスから期待する何を知っているようにMPI_Alltoall()への最初の呼び出しを使用することです。このグローバル通信は、すべてのプロセスが開始時に同期されるはずであるため、プロセス同期の面では問題ではありません。

これが完了すると、最初の問題は簡単になります。これは、ループMPI_Isend()と最後にMPI_Waitall()が続き、ループがMPI_Irecv()となるようにするだけで解決できます。しかし、私はむしろそれを可能にするために、同じことを行うためにここでMPI_Alltoallv()への呼び出しを使用しました。実際には、送信バッファと受信バッファはすでに存在している可能性が高く、必要なデータコピーを保存せずに正しい位置を指すように変位だけを計算する必要があります。

また、この部分は今や自明なので、コードのコンテキストで何が最善であるかはあなた次第です。

関連する問題