あなたの問題を暴露する方法から、最初に同期の問題はないように見えます。したがって、ここで私が提案するソリューションです:あなたが見ることができるように
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()
への呼び出しを使用しました。実際には、送信バッファと受信バッファはすでに存在している可能性が高く、必要なデータコピーを保存せずに正しい位置を指すように変位だけを計算する必要があります。
また、この部分は今や自明なので、コードのコンテキストで何が最善であるかはあなた次第です。
1つ(メッセージの完了を送信する)ともう1つ(受信を停止することを知っていること)は何ですか?最初のセクションでは、引用したセクションで説明したように、 'MPI_Issend'同期モードsendを使用することができます。第2の場合、(例えば、特別なタグによって示されるような)停止メッセージを送信する。 – Zulan
ランク1ランクは、1)すべてのメッセージが特定のランクに送信されているかどうかを知っている2)メッセージがいくつあるか。 1つのランクからのすべてのメッセージが異なる宛先に送信された後で障壁に到達すると、これを適切に同期するように見えます。バリアが完了すると、すべてのランクのすべてのメッセージがそれぞれのrecv –
MPI 3.2に到達しましたか?それは存在しますか?私が知っている最後のものは3.1ですが、多分私は何かを見逃しました...それを除いて、私はあなたの質問を理解していません。意味のあるコードスニペットを例に挙げてください。 – Gilles