2011-08-15 8 views
2

もしこの単純なMPIが送受信するコードがの2つのプロセッサで実行されない理由を誰かが教えてくれれば感謝します.n = 40(行20)の値がnの場合< = 30。言い換えれば、メッセージサイズが特定の数(これはそれほど大きくなく、約8100の1次元配列)を超えた場合、MPIはデッドロックします。単純なMPIプログラム

#include "mpi.h" 
#include "stdio.h" 
#include "stdlib.h" 
#include "iostream" 
#include "math.h" 
using namespace std; 

int main(int argc, char *argv[]) 
{ 
    int processor_count, processor_rank; 
    double *buff_H, *buff_send_H; 
    int N_pa_prim1, l, n, N_p0; 
    MPI_Status status; 

    MPI_Init (&argc, &argv); 
    MPI_Comm_size (MPI_COMM_WORLD, &processor_count); 
    MPI_Comm_rank (MPI_COMM_WORLD, &processor_rank); 

    N_pa_prim1=14; l=7; n=40; N_p0=7; 
    buff_H = new double [n*n*N_p0+1];   //Receive buffer allocation 

    buff_send_H = new double [n*n*N_p0+1];  //Send buffer allocation 

    for (int j = 0; j < n*n*N_p0+1; j++) 
     buff_send_H[j] = 1e-8*rand(); 

    if (processor_rank == 0) 
     MPI_Send(buff_send_H, n*n*N_p0+1, MPI_DOUBLE, 1, 163, MPI_COMM_WORLD); 
else if(processor_rank == 1) 
    MPI_Send(buff_send_H, n*n*N_p0+1, MPI_DOUBLE, 0, 163, MPI_COMM_WORLD); 

    MPI_Recv(buff_H, n*n*N_p0+1, MPI_DOUBLE, MPI_ANY_SOURCE, 163, MPI_COMM_WORLD, &status); 
cout << "Received successfully by " << processor_rank << endl; 
MPI_Finalize(); 
return 0; 
} 

答えて

4

デッドロックは正しい動作です。あなたのコードにデッドロックがあります。

MPI_Sendは、MPI_Ssendとして振る舞うことができます。つまり、ブロックされます。ブロッキング通信プリミティブは、ある意味では通信が「完了」するまで(ブロッキング送信の場合)おそらく受信が開始されたことを意味するまで戻らない。

あなたのコードは次のようになります。

If Processor 0: 
    Send to processor 1 

If Processor 1: 
    Send to processor 0 

Receive 

つまり - インクルードは、受信送信が完了するまで開始されません。あなたは送っていますが、誰も受け入れていないので、彼らは決して戻ってこないでしょう! (これは小さなメッセージのために働くという事実は実装上の成果物です - ほとんどのmpi実装は "十分に小さい"メッセージのためにいわゆる "熱心なプロトコル"を使用しますが、これは一般的に数えることはできません)

他の論理エラーもあることに注意してください。このプログラムは、2以上のプロセッサのデッドロックも発生します。ただし、rank> = 2のプロセッサは決して来ないメッセージを待っています。

あなたが交互にして、プログラムを修正することができますが、ランクによって送受信:

if (processor_rank == 0) { 
    MPI_Send(buff_send_H, n*n*N_p0+1, MPI_DOUBLE, 1, 163, MPI_COMM_WORLD); 
    MPI_Recv(buff_H, n*n*N_p0+1, MPI_DOUBLE, MPI_ANY_SOURCE, 163, MPI_COMM_WORLD, &status); 
} else if (processor_rank == 1) { 
    MPI_Recv(buff_H, n*n*N_p0+1, MPI_DOUBLE, MPI_ANY_SOURCE, 163, MPI_COMM_WORLD, &status); 
    MPI_Send(buff_send_H, n*n*N_p0+1, MPI_DOUBLE, 0, 163, MPI_COMM_WORLD); 
} 

か(ブロック(受信+送信)、というよりもブロッキング送信+ブロッキング受信です)MPI_Sendrecvを使用して:

int sendto; 
if (processor_rank == 0) 
    sendto = 1; 
else if (processor_rank == 1) 
    sendto = 0; 

if (processor_rank == 0 || processor_rank == 1) { 
    MPI_Sendrecv(buff_send_H, n*n*N_p0+1, MPI_DOUBLE, sendto, 163, 
       buff_H, n*n*N_p0+1, MPI_DOUBLE, MPI_ANY_SOURCE, 163, 
       MPI_COMM_WORLD, &status); 
} 

または非ブロッキングを使用して送信し、受信:

MPI_Request reqs[2]; 
MPI_Status statuses[2]; 
if (processor_rank == 0) { 
    MPI_Isend(buff_send_H, n*n*N_p0+1, MPI_DOUBLE, 1, 163, MPI_COMM_WORLD, &reqs[0]); 
} else if (processor_rank == 1) { 
    MPI_Isend(buff_send_H, n*n*N_p0+1, MPI_DOUBLE, 0, 163, MPI_COMM_WORLD, &reqs[0]); 
} 

if (processor_rank == 0 || processor_rank == 1) 
    MPI_Irecv(buff_H, n*n*N_p0+1, MPI_DOUBLE, MPI_ANY_SOURCE, 163, MPI_COMM_WORLD, &reqs[1]); 

MPI_Waitall(2, reqs, statuses); 
0

助けてくれてありがとうジョナサン。ここで私は第3の解決法を選択し、あなたのものに同様のコードを書いて、 "for"ループを追加していくつかのメッセージを送ることを除いています。今回はデッドロックしません。プロセッサは最後のメッセージだけを受信し続ける。

#include <mpi.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <iostream> 
#include <math.h> 
using namespace std; 

int main(int argc, char *argv[]) 
{ 
int processor_count, processor_rank; 

//Initialize MPI 
MPI_Init (&argc, &argv); 
MPI_Comm_size (MPI_COMM_WORLD, &processor_count); 
MPI_Comm_rank (MPI_COMM_WORLD, &processor_rank); 

double **buff_H, *buff_send_H; 
int N_pa_prim1, l, n, N_p0, count, temp; 
N_pa_prim1=5; l=7; n=50; N_p0=7; 

MPI_Request reqs[N_pa_prim1]; 
MPI_Status statuses[N_pa_prim1]; 
buff_H = new double *[N_pa_prim1];     //Receive buffer allocation 
for (int i = 0; i < N_pa_prim1; i++) 
    buff_H[i] = new double [n*n*N_p0+1]; 
buff_send_H = new double [n*n*N_p0+1];    //Send buffer allocation 

if (processor_rank == 0) { 
    for (int i = 0; i < N_pa_prim1; i++){ 
     for (int j = 0; j < n*n*N_p0+1; j++) 
      buff_send_H[j] = 2.0325e-8*rand(); 

     cout << processor_rank << "\t" << buff_send_H[n*n*N_p0] << "\t" << "Send" << "\t" << endl; 
     MPI_Isend(buff_send_H, n*n*N_p0+1, MPI_DOUBLE, 1, 163, MPI_COMM_WORLD, &reqs[i]); 
    } 
} 
else if (processor_rank == 1) { 
    for (int i = 0; i < N_pa_prim1; i++){ 
     for (int j = 0; j < n*n*N_p0+1; j++) 
      buff_send_H[j] = 3.5871e-8*rand(); 

     cout << processor_rank << "\t" << buff_send_H[n*n*N_p0] << "\t" << "Send" << "\t" << endl; 
     MPI_Isend(buff_send_H, n*n*N_p0+1, MPI_DOUBLE, 0, 163, MPI_COMM_WORLD, &reqs[i]); 
    } 
} 

for (int i = 0; i < N_pa_prim1; i++) 
    MPI_Irecv(buff_H[i], n*n*N_p0+1, MPI_DOUBLE, MPI_ANY_SOURCE, 163, MPI_COMM_WORLD, &reqs[N_pa_prim1+i]); 

MPI_Waitall(2*N_pa_prim1, reqs, statuses); 

for (int i = 0; i < N_pa_prim1; i++) 
    cout << processor_rank << "\t" << buff_H[i][n*n*N_p0] << "\t" << "Receive" << endl; 

MPI_Finalize(); 
return 0; 

}

を(メッセージが長いことから、私は唯一の整合性をチェックするために彼らの最後の要素を印刷しました)
関連する問題