私は、各プロセッサがいくつかの他のプロセッサに複数のメッセージを送り、MPI_Isend
を使用していくつかの未知数のメッセージを受信するアプリケーションに取り組んでいます。受信者側から、MPI_Isendを使用して送信されたすべてのメッセージが受信されたことを確認するにはどうすればよいですか?
私の小さなサンプルプログラム(コード)私は4つのプロセッサーが残りの3つのプロセッサーのそれぞれに4つのメッセージを送信しているので、各プロセッサーは12のメッセージを受信することになっています。
私が見ている問題は、私のマシンが幸せであるとき、私のプログラムは、以下の
Rank 2 receives 12 msgs; Global count = 48
Rank 1 receives 12 msgs; Global count = 48
Rank 3 receives 12 msgs; Global count = 48
Rank 0 receives 12 msgs; Global count = 48
を出力しかし、それはになっていてたまに、一部のプロセッサだけで十分なメッセージを受信していないということです。
Rank 1 receives 9 msgs; Global count = 37
Rank 3 receives 12 msgs; Global count = 37
Rank 2 receives 4 msgs; Global count = 37
Rank 0 receives 12 msgs; Global count = 37
私はこの問題は、私は、着信メッセージをチェックして、すぐにチェックがfalseを返すように、ループを終了するにはMPI_Iprobe
を使用するwhile-loop
となる可能性が知っています。 しかし、私はこれをどうやって違う方法で行うことができるのか分かりません。言い換えれば、すべてのプロセッサがMPI_Allreduce
ステートメントに到達するまでに受け取るべきすべてのメッセージを受信するようにするにはどうすればよいですか?
私のプログラムは次のようになります。
#include "mpi.h"
#include <stdbool.h>
#include "stdio.h"
#include "stdlib.h"
int main(int argc, char* argv[])
{
MPI_Init(&argc, &argv);
int rank, p;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &p);
//ASSUMPTION: using 4 procs
//Don't worry about this part.
//just some stupid way to determine the receivers.
// Irrelevant to the question.
int recvs[3];
int i = 0, nei = 0;
for (; nei < 4; ++nei)
{
if (nei != rank)
{
recvs[i] = nei;
++i;
}
}
//Proc sending msgs to its neighbors.
//In this case, it's all other procs. (but in my real app, it's almost never the case)
int TAG = 0;
int buff[4] = {555, 666, 777, 888};
int local_counts[4] = {0, 0, 0, 0}; //EDIT 1
for (nei = 0; nei < 3; ++nei)
{
for (i = 0; i < 4; ++i)
{
MPI_Request req;
MPI_Isend(&buff[i], 1, MPI_INT, recvs[nei], TAG, MPI_COMM_WORLD, &req);
local_counts[recvs[nei]] += 1; //EDIT 1
}
}
//EDIT 1: tell processors how many msgs they're supposed to get
int global_counts[4];
int expectedRecvCount;
MPI_Reduce(local_counts, global_counts, 4, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
MPI_Scatter(global_counts, 1, MPI_INT, &expectedRecvCount, 1, MPI_INT, 0, MPI_COMM_WORLD);
//Receiving
int recvCount = 0;
MPI_Status status;
int hasMsg = 0;
int num;
do
{
MPI_Iprobe(MPI_ANY_SOURCE, TAG, MPI_COMM_WORLD, &hasMsg, &status);
if (hasMsg)
{
MPI_Recv(&num, 1, MPI_INT, status.MPI_SOURCE, TAG, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
++recvCount;
printf("\nRank %d got %d from %d", rank, num, status.MPI_SOURCE);
}
}
while (recvCount < expectedRecvCount); //EDIT 1
//while (hasMsg);
//Total number msgs received by all procs.
//Now here's where I see the problem!!!
MPI_Allreduce(&recvCount, &global_count, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
printf("\nRank %d receives %d msgs; Global count = %d", rank, recvCount, global_count);
MPI_Finalize();
return 0;
}
============================ ===============私は考えることができる
EDIT 1
一つのアプローチは、各プロセッサは、それが他のすべてのプロセッサを送信されたメッセージの数を追跡することです。その後、送信操作が完了した後、私はMPI_Reduce
を実行し、次にこれらのメッセージ数ではMPI_Scatter
を実行します。そうすれば、各プロセッサは受信するメッセージの数を知ることができます。 (コードを参照してください) 誰もこのアプローチのパフォーマンスについてコメントできますか?パフォーマンスを潜在的かつ真剣に妨げてしまうでしょうか?
ありがとう@Angelos!私は実際にメッセージカウンターを使うことを考えています。投稿の編集を参照してください。 – 0x56794E
@Angelosのソリューションは、IMHOであり、集合的なコミュニケーションを含むあらゆるものよりはるかにエレガントです。その正確さは、MPIがメッセージの順序付けを維持していること、すなわち、MPI_ANY_TAGがreceiveTAGメッセージに一致する前にTAG *としてタグ付けされたすべてのメッセージと一致することが保証されているという事実に依存することが重要です。 –