2017-02-08 3 views
0

私はという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_SendMPI_Recvでは不可能です。したがって、MPI_IrecvMPI_SendMPI_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 

答えて

2

あなたMPI_Waitまたは成功したMPI_TestMPI_Irecvからデータにアクセスする前に完了する必要があります。それを障壁で置き換えることはできません。

リング通信の場合は、MPI_Sendrecvを使用することを検討してください。非同期通信を使用するよりも単純にすることができます。

+0

私はコードでMPI_Waitを使用していたことに気付きましたか?うまく行かなかった。私がMPI_Waitだけを使用したときに、すべてのプロセッサが待機していました...? – kundilcas

+2

あなたのコードには**のコメント付きの 'MPI_Wait'があります。私の答えはあなたの直接の問題に取り組んでおり、手動の非ブロッキング通信なしでこれに対処するための一般的な代替方法を推奨しています。あなたの場合、 'MPI_Wait'がなぜ完了していないのかをさらに調査したい場合。それと[mcve]を投稿してください。 '&request [my_rank]'はコンパイルされないので、あなたのコードは一般に偽であることに注意してください。これは、コードがあなたの実際のコードを表すものではないと私に信じさせてくれます。 – Zulan

+0

男性はいません!この問題を解決するために、私はリクエスト配列をリクエスト変数に変更しました。そのような部分を更新するのを忘れました。今、私はそれを更新しました。ちなみに、このコードを偽のものと見なすには、コードによって出力される出力があります...とにかく、このシナリオから、最小限の完全な例はなく、あなたの提案は何ですか? – kundilcas

関連する問題