次のような MPI C コードがあります。
for(i=0;i<NTask;i++)
{
got_initial_bit_of_data[i]=0;
if(need_to_communicate with i)
MPI_ISend(&bit_of_pre_data_for_i,1,MPI_INT,partner,0,MPI_COMM_WORLD,&pre_requests[i]);
}
while(1)
{
MPI_Testsome(NTask,pre_requests,&ndone,idxs,MPI_STATUSES_IGNORE)
if(ndone)
{
for(i=0;i<ndone;i++)
{
MPI_ISend(&the_main_block_of_data_for_i,size_of_block,MPI_BYTE,idxs[i],1,MPI_COMM_WORLD,&main_requests[idxs[i]]);
}
}
//Other stuff that doesn't matter
MPI_IProbe(MPI_ANY_SOURCE,0,MPI_COMM_WORLD,&flag,&status);
if(!flag)
{
MPI_IProbe(MPI_ANY_SOURCE,1,MPI_COMM_WORLD,&flag,&status);
}
if(flag)
{
//Receiving the initial little bit of data
if(status.MPI_TAG==0)
{
//Location 1
got_initial_bit_of_data[status.MPI_SOURCE]=1;
MPI_Recv(&useful_location,1,MPI_INT,status.MPI_SOURCE,MPI_STATUS_IGNORE);
}
//Receiving the main bit of data
else if(status.MPI_TAG==1)
{
//Location 2
if(got_initial_bit_of_data[status.MPI_SOURCE]!=1)
//Something has gone horribly wrong...
//Receive the main bit of data here...
}
}
}
完全なコードは数百行の長さであるため、明らかに多くの詳細を省略しています。私が行ったことが少し奇妙に見える場合、それはおそらく、省略されたコード ブロック内の何かが原因である可能性があります。
アイデアは、最初に各プロセッサが「アナウンスメント」メッセージを通信したいプロセッサに送信するというものです。これらのプロセッサがこのメッセージを受信したことを検出すると (つまり、MPI_Testsome が「アナウンスメント」MPI_Isend が完了したことを示したとき)、大量のデータを送信する必要があります。
データを受信するプロセッサの観点からは、最初に位置 1 でアナウンス メッセージを受信する必要があります。これにより、MPI_Testsome は Isend が完了したことを示し、データの大きなチャンクを送信します。受信プロセッサは、位置 2 でデータのメイン ブロックを受信する必要があります。このロジックに従うと、got_initial_bit_of_data[status.MPI_SOURCE] が 0 の状態で位置 2 に到達することは不可能ですが、これはまさに非常にまれに発生することであり、私は理由を解明するのが好きです。
コードのロジックが間違っているか、欠落している IProbe と Testsome の微妙な部分があります。
また、このコード ブロック全体を終了して再入力します。さまざまなプロセッサがさまざまな時点で出入りしますが、すべての ISend が処理された場合のみです (Testsome が完了したと判断した場合)。
上記の説明が意味をなさない場合、私が知りたいのは、一致する受信が完了せずに (または開始さえせずに) ISend が完了したと Testsome が主張する状況があるかどうかです。たとえば、プロセッサが IProbe を呼び出すだけで、Testsome は要求が完了したと見なすことができますか?