2016-06-25 6 views
3

ノードがメッセージの受信者であるかどうかを確認する方法はありますか?このような何か:メッセージがMPIで利用できるかどうかを確認するには?

int MPI_HasMessage()

は私が仕事をしてループを記述しようとしていますし、別のノードが解決策を見つけた場合は、ルートノード(rank = 0)によって中断されています。さもなければそれは続行する

for(int i = 0; i < workload; i++) 
{ 
    doWork(); 
    if(MPI_HasMessage()) 
    { 
     MPI_recv(...); 
    } 
} 
+0

、非ブロックの集合を使用することの可能な複製である[検索/ MS-MPIのいずれかの伝送を待つ] http://stackoverflow.com/questionsを提案します/ 20017814/search-wait-for-any-ms-mpi) –

答えて

2

受信メッセージを実際に受信せずに確認できる機能MPI_Iprobe()が必要です。

プロセス0がMPI_Isend()を使用してメッセージを自分自身に送信した後、それをプローブして最後にMPI_Recv()を使用してメッセージを受信する例があります(there)。

次のCコードは、MPI_ANY_SOURCEを使用して、コミュニケータの任意のプロセスからのメッセージをプローブします。これはmpicc main.c -o main -Wallによってコンパイルされ、mpirun -np 4 mainによって実行されます。

#include <mpi.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <time.h> 

int main(int argc,char *argv[]) 
{ 
    int size, rank; 
    MPI_Init(&argc,&argv); 
    MPI_Comm_size(MPI_COMM_WORLD,&size); 
    MPI_Comm_rank(MPI_COMM_WORLD,&rank); 

    MPI_Status status; 

    srand(time(NULL)); 
    int r=0;  
    if(rank==0){ 
     r = rand()%size; // ugly random, not even uniformly distributed 

    } 
    MPI_Bcast(&r,1,MPI_INT,0,MPI_COMM_WORLD); 

    MPI_Request request=MPI_REQUEST_NULL; 
    if(rank==r){ 
     MPI_Isend(&r,1,MPI_INT,0,0,MPI_COMM_WORLD,&request); 
    } 

    if(rank==0){ 
     int flag=0; 

     // probing the message 
     while(!flag) 
     { 
      // probing on a regular basis, process zero can do anything there 
      int i; 
      int coffee=42; 
      for(i=0;i<1000000;i++){ 
       coffee+=1; 
      } 

      MPI_Iprobe(MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, &flag, &status); 
     } 

     // the status argument retruned by the function could have been used to make sure that 
     // MPI_Recv receives the probed message. MPI_Get_count(&status, MPI_INT, &count); 
     // could have been added to retrieve the length of the message 
     MPI_Recv(&r, 1, MPI_INT,MPI_ANY_SOURCE , 0, MPI_COMM_WORLD, &status); 

     printf("process 0 got %d\n",r); 
    } 


    MPI_Wait(&request, &status); 

    MPI_Finalize(); 
    return 0; 
} 
2

あなたの質問に正解があります。しかし、これは実際にはXY-problemのインスタンスです。

あなたの実際の質問は次のとおりです。

1は、溶液

を発見した場合、これはありません1単純な答えと共通の問題であると思われる方法のすべてのプロセスに通知するために、What is the right way to “notify” processors without blocking?のための質問と答えをチェック。

あなたは間違いなくMPI_Iprobeを使用する必要はありません。MPI_Irecvで事前投稿されたメッセージは問題ありません。私は(my answer

によりdefailtで説明したように
#include <stdio.h> 
#include <stdlib.h> 
#include <mpi.h> 

const int iter_max = 10000; 
const int difficulty = 20000; 

int find_stuff() 
{ 
    int num_iters = rand() % iter_max; 
    for (int i = 0; i < num_iters; i++) { 
     if (rand() % difficulty == 0) { 
      return 1; 
     } 
    } 
    return 0; 
} 

const int stop_tag = 42; 
const int root = 0; 

int forward_stop(MPI_Request* root_recv_stop, MPI_Request* all_recv_stop, int found_count) 
{ 
    int flag; 
    MPI_Status status; 
    if (found_count == 0) { 
     MPI_Test(root_recv_stop, &flag, &status); 
    } else { 
     // If we find something on the root, we actually wait until we receive our own message. 
     MPI_Wait(root_recv_stop, &status); 
     flag = 1; 
    } 
    if (flag) { 
     printf("Forwarding stop signal from %d\n", status.MPI_SOURCE); 
     MPI_Ibarrier(MPI_COMM_WORLD, all_recv_stop); 
     MPI_Wait(all_recv_stop, MPI_STATUS_IGNORE); 
     // We must post some additional receives if multiple ranks found something at the same time 
     MPI_Reduce(MPI_IN_PLACE, &found_count, 1, MPI_INT, MPI_SUM, root, MPI_COMM_WORLD); 
     for (found_count--; found_count > 0; found_count--) { 
      MPI_Recv(NULL, 0, MPI_CHAR, MPI_ANY_SOURCE, stop_tag, MPI_COMM_WORLD, &status); 
      printf("Additional stop from: %d\n", status.MPI_SOURCE); 
     } 
     return 1; 
    } 
    return 0; 
} 

int main() 
{ 
    MPI_Init(NULL, NULL); 

    int rank; 
    MPI_Comm_rank(MPI_COMM_WORLD, &rank); 
    srand(rank); 

    MPI_Request root_recv_stop; 
    MPI_Request all_recv_stop; 
    if (rank == root) { 
     MPI_Irecv(NULL, 0, MPI_CHAR, MPI_ANY_SOURCE, stop_tag, MPI_COMM_WORLD, &root_recv_stop); 
    } else { 
     // You may want to use an extra communicator here, to avoid messing with other barriers 
     MPI_Ibarrier(MPI_COMM_WORLD, &all_recv_stop); 
    } 

    while (1) { 
     int found = find_stuff(); 
     if (found) { 
      printf("Rank %d found something.\n", rank); 
      // Note: We cannot post this as blocking, otherwise there is a deadlock with the reduce 
      MPI_Request req; 
      MPI_Isend(NULL, 0, MPI_CHAR, root, stop_tag, MPI_COMM_WORLD, &req); 
      if (rank != root) { 
       // We know that we are going to receive our own stop signal. 
       // This avoids running another useless iteration 
       MPI_Wait(&all_recv_stop, MPI_STATUS_IGNORE); 
       MPI_Reduce(&found, NULL, 1, MPI_INT, MPI_SUM, root, MPI_COMM_WORLD); 
       MPI_Wait(&req, MPI_STATUS_IGNORE); 
       break; 
      } 
      MPI_Wait(&req, MPI_STATUS_IGNORE); 
     } 
     if (rank == root) { 
      if (forward_stop(&root_recv_stop, &all_recv_stop, found)) { 
       break; 
      } 
     } else { 
      int stop_signal; 
      MPI_Test(&all_recv_stop, &stop_signal, MPI_STATUS_IGNORE); 
      if (stop_signal) 
      { 
       MPI_Reduce(&found, NULL, 1, MPI_INT, MPI_SUM, root, MPI_COMM_WORLD); 
       printf("Rank %d stopping after receiving signal.\n", rank); 
       break; 
      } 
     } 
    }; 

    MPI_Finalize(); 
} 
関連する問題