2013-02-26 16 views
5

C言語のMPIプログラムにはほとんど問題がありません。MPI_Send、MPI_Irecv、MPI_Testを使用して、スレーブからMPI_Sendへの2つのメッセージを送りたいです。その後、私は無限ループをして、私は常にスレーブからメッセージを受け取ります-1(status.MPI_Sourceによると)。MPI_IrecvとMPI_Testを使用した無限ループ

私は未知のプロセスからのすべてのこれらのメッセージを受け取り、なぜ私は理解していない(-1)...

マイコード:

#include <stdio.h> 
#include <mpi.h> 
#include <sys/time.h> 

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

int rank, size; 
MPI_Status status; 

/* Init */ 
MPI_Init(&argc, &argv); 
MPI_Comm_rank(MPI_COMM_WORLD, &rank); 
MPI_Comm_size(MPI_COMM_WORLD, &size); 

if (rank != 0) { // Slaves 
    int buf; 

    if (rank == 1) { 
     buf = 1; 
     MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); 
    } 
    if (rank == 2) { 
     buf = 2; 
     MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); 
    } 

} 
else { // Master 
    int sum = 0; 
    int flag, res; 
    MPI_Request request; 
    MPI_Status status; 

    MPI_Irecv(&res, 1, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &request); 

    while (1) { 
     flag = 0; 

     MPI_Test(&request, &flag, &status); 

     if (flag != 0) { 
      printf("recv : %d, slave : %d\n", res, status.MPI_SOURCE); 
      if (status.MPI_SOURCE != -1) 
       sum += res; 
     } 
     else 
      printf("fail!\n"); 

     if (sum == 3) 
      break; 
    } 

    printf("sum : %d\n", sum); 
} 

MPI_Finalize(); 
return 0; 

} 

感謝。

PS:申し訳ありませんが私の英語

答えて

4

問題については、マスターがしか1が受信ポストということです。 MPI_Testが返されたところで(if (status.MPI_SOURCE != -1)ブロック内)、ループ内のMPI_Irecvにコールを移動する必要があります。これにより、後続のメッセージを受信できるようになります。

9

メッセージを受け取るたびにMPI_Irecvを呼び出す必要があります。あなたの場合は、2回呼び出す必要があります。それ以上はない。

はループ内MPI_Irecvコールを移動することによって変更コードで見てみましょう。 これは間違っています。動作しないでしょう。 |時間の モーメント:

else { // Master 
int sum = 0; 
int flag, res; 
MPI_Request request; 
MPI_Status status; 

while (1) { 
    flag = 0; 
    MPI_Irecv(&res, 1, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &request); 
    MPI_Test(&request, &flag, &status); 
    if (flag != 0) { 
     printf("recv : %d, slave : %d\n", res, status.MPI_SOURCE); 
     if (status.MPI_SOURCE != -1) 
      sum += res; 
    } 
    else 
     printf("fail!\n"); 

    if (sum == 3) 
     break; 
} 

それはそのような状況を想像するのは簡単です(常に私たちは、分散システムまたはスレッドについて話している場合である)スレーブによってsendedではメッセージを配信するのランダムな時間を仮定すると、イベント

0    | called first MPI_Irecv, allocated memory for MPI_Request object 
1    | called second MPI_Irecv, allocated memory for MPI_Request (lets say) object2 
2    | called third MPI_Irecv, allocated memory for MPI_Request object3 
3    | called MPI_Send in slave no. 1 
4    | called MPI_Send in slave no. 2 
5    | received message by master from slave no. 1, filled object, flag variable still 0 because its related to object3 
6    | received message by master from slave no. 2, filled object2, flag variable still 0 because its related to object3 
7,8,9...  | infinite loop, flag still has value 0 
n   | error: MPI_Irecv(147): MPI_Irecv(buf=0x7fffecfa60c4, count=1, MPI_INT, src=MPI_ANY_SOURCE, tag=MPI_ANY_TAG, MPI_COMM_WORLD, request=0x7fffecfa60c8) 
MPID_Irecv(53): failure occurred while allocating memory for a request object 

2つの解決策があります。ループ中にsleep(3)を呼び出すことでMasterプロセスを遅くすることができますので、MPI_Sendが呼び出された後で確実に開始されます。

第二には、より優れたエンジニアリングのアプローチは、私たちがメッセージを期待しているだけMPI_Irecvを呼び出すことです。最初にMPI_Irecvを呼び出し、フラグに値0を割り当てます。メッセージ変更フラグを-1に戻した後、フラグが-1の場合にのみMPI_Irecvを呼び出します。ここで

は、それがを動作するコードです:

#include <stdio.h> 
#include <mpi.h> 
#include <sys/time.h> 

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

int rank, size; 
MPI_Status status; 

/* Init */ 
MPI_Init(&argc, &argv); 
MPI_Comm_rank(MPI_COMM_WORLD, &rank); 
MPI_Comm_size(MPI_COMM_WORLD, &size); 

if (rank != 0) { // Slaves 
    int buf; 

    if (rank == 1) { 
     buf = 1; 
     MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); 
    } 
    if (rank == 2) { 
     buf = 2; 
     MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); 
    } 

} 
else { // Master 
    int sum = 0; 
    int flag = -1, res; 
    MPI_Request request; 
    MPI_Status status; 
    while (1) { 
    if(flag != 0) 
    { 
     MPI_Irecv(&res, 1, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &request); 
     flag = 0; 
    } 
     MPI_Test(&request, &flag, &status); 

     if (flag != 0) { 
      printf("recv : %d, slave : %d\n", res, status.MPI_SOURCE); 
      if (status.MPI_SOURCE != -1) 
       sum += res; 
     flag = -1; 
     } 


     if (sum == 3) 
      break; 
    } 

    printf("sum : %d\n", sum); 
} 

MPI_Finalize(); 
return 0; 

} 
関連する問題