私はという1D行列データを持っています。各反復では、各プロセッサはQ_send_matrix
を更新し、前のプロセッサ(rank-1
)に送信しますが、次のプロセッサ(rank+1
)から新しく更新された行列Q_recv_matrix
を受け取ります。たとえば、反復では、Proc[0]
はQ_send_matrix
を更新し、Proc[3]
に送信しますが、Proc[1]
からはQ_recv_matrix
を受け取ります。あなたが推測しているように、それはリング通信のようなものです。以下のコードの後にのコードを見てください。MPI_IrecvがMPI_Sendによって送信されたデータを正しく受信しない
MPI_Request request;
MPI_Status status;
// All the elements of Q_send and Q_recv buffers
// are set to 1.0 initially. Each processor
// updates its Q_send buffer to prepare it
// to be sent below.(above part is big, so it
// is not added here...)
/**
* Transfer Q matrix blocks among processors
* + Each processor sends the Q matrix
* + to the previous processor while receives
* + the Q matrix from the next processor
* + It is like a ring communication
* */
/* Receive Q matrix with MPI_Irecv */
source = (my_rank+1)%comm_size;
recv_count = no_col_per_proc[source]*input_k;
MPI_Irecv(Q_recv_matrix, recv_count,
MPI_FP_TYPE, source,
0, MPI_COMM_WORLD,
&request);
/* Send Q matrix */
dest = (my_rank-1+comm_size)%comm_size;
send_count = no_col_per_proc[my_rank]*input_k;
MPI_Send(Q_send_matrix, send_count,
MPI_FP_TYPE, dest,
0, MPI_COMM_WORLD);
/* Wait status */
// MPI_Wait(request, status);
/* Barrier */
MPI_Barrier(MPI_COMM_WORLD);
/* Print Q send and receive matrices */
for(j = 0; j < send_count; j ++)
{
printf("P[%d] sends Q_send[%d] to P[%d] = %.2f\n",
my_rank, j, dest, Q_send_matrix[j]);
}
for(j = 0; j < recv_count; j ++)
{
printf("P[%d] receives Q_recv[%d] from P[%d] = %.2f\n",
my_rank, j, source, Q_recv_matrix[j]);
}
私はこの通信を同期して行います。ただし、ブロッキング機能に基づいてデッドロックが発生するため、MPI_Send
とMPI_Recv
では不可能です。したがって、MPI_Irecv
とMPI_Send
をMPI_Wait
と一緒に使用しました。しかし、それは完了していない、すべてのプロセッサが待っていた。だから、MPI_Wait
の代わりにMPI_Barrier
を入れて、それらを同期させ、プロセッサの待機問題を解決して作業を終えた。しかし、正しく動作しませんでした。次のようなコードの出力は間違っています。各プロセッサは正しいデータを送信し、送信側で問題はありません。一方、受信データバッファには変更はありません。これは、いくつかのプロセッサでは、次のように他のプロセッサの1つからデータを受信しても、受信バッファの初期値が残っていることを意味します。
P[0] sends Q_send[0] to P[3] = -2.12
P[0] sends Q_send[1] to P[3] = -2.12
P[0] sends Q_send[2] to P[3] = 4.12
P[0] sends Q_send[3] to P[3] = 4.12
P[0] receives Q_recv[0] from P[1] = 1.00
P[0] receives Q_recv[1] from P[1] = 1.00
P[0] receives Q_recv[2] from P[1] = 1.00
P[0] receives Q_recv[3] from P[1] = 1.00
P[1] sends Q_send[0] to P[0] = -2.12
P[1] sends Q_send[1] to P[0] = -2.12
P[1] sends Q_send[2] to P[0] = 0.38
P[1] sends Q_send[3] to P[0] = 0.38
P[1] receives Q_recv[0] from P[2] = 1.00
P[1] receives Q_recv[1] from P[2] = 1.00
P[1] receives Q_recv[2] from P[2] = 1.00
P[1] receives Q_recv[3] from P[2] = 1.00
P[2] sends Q_send[0] to P[1] = 1.00
P[2] sends Q_send[1] to P[1] = 1.00
P[2] sends Q_send[2] to P[1] = -24.03
P[2] sends Q_send[3] to P[1] = -24.03
P[2] receives Q_recv[0] from P[3] = 1.00
P[2] receives Q_recv[1] from P[3] = 1.00
P[2] receives Q_recv[2] from P[3] = 1.00
P[2] receives Q_recv[3] from P[3] = 1.00
P[3] sends Q_send[0] to P[2] = 7.95
P[3] sends Q_send[1] to P[2] = 7.95
P[3] sends Q_send[2] to P[2] = 0.38
P[3] sends Q_send[3] to P[2] = 0.38
P[3] receives Q_recv[0] from P[0] = -2.12
P[3] receives Q_recv[1] from P[0] = -2.12
P[3] receives Q_recv[2] from P[0] = 4.12
P[3] receives Q_recv[3] from P[0] = 4.12
私はコードでMPI_Waitを使用していたことに気付きましたか?うまく行かなかった。私がMPI_Waitだけを使用したときに、すべてのプロセッサが待機していました...? – kundilcas
あなたのコードには**のコメント付きの 'MPI_Wait'があります。私の答えはあなたの直接の問題に取り組んでおり、手動の非ブロッキング通信なしでこれに対処するための一般的な代替方法を推奨しています。あなたの場合、 'MPI_Wait'がなぜ完了していないのかをさらに調査したい場合。それと[mcve]を投稿してください。 '&request [my_rank]'はコンパイルされないので、あなたのコードは一般に偽であることに注意してください。これは、コードがあなたの実際のコードを表すものではないと私に信じさせてくれます。 – Zulan
男性はいません!この問題を解決するために、私はリクエスト配列をリクエスト変数に変更しました。そのような部分を更新するのを忘れました。今、私はそれを更新しました。ちなみに、このコードを偽のものと見なすには、コードによって出力される出力があります...とにかく、このシナリオから、最小限の完全な例はなく、あなたの提案は何ですか? – kundilcas