私はMPIを初めて使用するので、気楽に行ってください...とにかく、非ブロッキング通信にMPI_IsendとMPI_Irecvを使用しようとしています。隣接するサブドメイン間でハローセルを交換する必要があるたびに呼び出したい「halo_exchange」というサブルーチンを作成しました。ドメインを適切に分割することができ、各ネイバーのランクを知っています。以下のコードでは、ネイバーは北/南に向けられています(つまり、1D行分解を使用します)。計算にはすべてのプロセスが使用されます。つまり、すべてのプロセスがこのサブルーチンを呼び出し、データを交換する必要があります。
元々、北と南の両方の境界に対して一連のMPI_Isend / MPI_Irecv呼び出しを使用していましたが、関数に「MPI_PROC_NULL」を渡すことに何か問題があるのではないかと考えて分割しました(境界は周期的ではありません)。これがifステートメントの理由です。コードは「MPI_Waitall」ステートメントでハングアップし続けますが、理由がわかりません。文字通り待つだけで、何を待っているのかわかりませんか?
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
//---------------------------------------------------------------------------------------
// FUNCTION "halo_exchange"
//---------------------------------------------------------------------------------------
void halo_exchange(PREFIX **array, MPI_Comm topology_comm, \
int nn, int S_neighbor, int N_neighbor)
{
int halo = 2;
int M = 20;
...
double *S_Recv,*N_Recv;
double *S_Send,*N_Send;
// Receive buffers
S_Recv = (double *) calloc( M*halo,sizeof(double) );
N_Recv = (double *) calloc( M*halo,sizeof(double) );
// Send buffers
S_Send = (double *) calloc( M*halo,sizeof(double) );
N_Send = (double *) calloc( M*halo,sizeof(double) );
...
// send buffers filled with data
// recv buffers filled with zeros (is this ok...or do I need to use malloc?)
...
if (S_neighbor == MPI_PROC_NULL)
{
MPI_Status status[2];
MPI_Request req[2];
MPI_Isend(&N_Send,halo*M,MPI_DOUBLE,N_neighbor,2,topology_comm,&req[0]);
MPI_Irecv(&N_Recv,halo*M,MPI_DOUBLE,N_neighbor,2,topology_comm,&req[1]);
...
...
MPI_Waitall(2,req,status);
}
else if (N_neighbor == MPI_PROC_NULL)
{
MPI_Status status[2];
MPI_Request req[2];
MPI_Isend(&S_Send,halo*M,MPI_DOUBLE,S_neighbor,1,topology_comm,&req[0]);
MPI_Irecv(&S_Recv,halo*M,MPI_DOUBLE,S_neighbor,1,topology_comm,&req[1]);
...
...
MPI_Waitall(2,req,status);
}
else
{
MPI_Status status[4];
MPI_Request req[4];
MPI_Isend(&S_Send,halo*M,MPI_DOUBLE,S_neighbor,1,topology_comm,&req[0]);
MPI_Isend(&N_Send,halo*M,MPI_DOUBLE,N_neighbor,2,topology_comm,&req[1]);
MPI_Irecv(&N_Recv,halo*M,MPI_DOUBLE,N_neighbor,2,topology_comm,&req[2]);
MPI_Irecv(&S_Recv,halo*M,MPI_DOUBLE,S_neighbor,1,topology_comm,&req[3]);
...
...
MPI_Waitall(4,req,status);
}
...
}
これは私の最初の理解でしたが、明らかに何かが欠けています。各プロセスがこのサブルーチンを呼び出すため、すべてのsend/recv関数が呼び出されます。次に、すべてのプロセスは、対応する通信が行われるのをMPI_Waitallポイントで待機します。彼らが終わったとき、それは動きます....誰かが私のものが動かない理由を教えてもらえますか?また、私は「タグ」の議論についてあまり明確ではありません(手がかり?)事前にすべてのあなたの助けに感謝します!!!