2014-01-29 28 views
0

我有NT循環(數百萬次迭代)爲大於0的過程。120字節的消息發送到每個迭代的過程0和過程0接收它們(我有相同的循環在NT上爲proc 0)。MPI Send/Recv數以百萬計的郵件

我想proc 0接收它們,所以我可以將它們存儲在數組nhdr1中。

問題是proc 0沒有正確接收消息,並且我經常在數組nhdr中使用0值。

如何修改代碼以便按照相同的順序接收消息?

[...] 
    if (rank == 0) { 

     nhdr = malloc((unsigned long)15*sizeof(*nhdr)); 
     nhdr1 = malloc((unsigned long)NN*15*sizeof(*nhdr1)); 

     itr = 0; 
     jnode = 1; 

     for (l=0; l<NT; l++) { 

      MPI_Recv(nhdr, 15, MPI_LONG, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status); 

      if (l == status.MPI_TAG) { 
       for (i=0; i<nkeys; i++) 
        nhdr1[itr*15+i] = nhdr[i]; 
      } 

      itr++; 

      if (itr == NN) { 
       ipos = (unsigned long)(jnode-1)*NN*15*sizeof(*nhdr1); 

       fseek(ismfh, ipos, SEEK_SET); 
       nwrite += fwrite(nhdr1, sizeof(*nhdr1), NN*15, ismfh); 

       itr = 0; 
       jnode++; 
      } 
     } 

     free(nhdr); 
     free(nhdr1); 

    } else { 

     nhdr = malloc(15*sizeof(*nhdr)); 

     irecmin = (rank-1)*NN+1; 
     irecmax = rank*NN; 

     for (l=0; l<NT; l++) { 
      if (jrec[l] >= irecmin && jrec[l] <= irecmax) { 

       indx1 = (unsigned long)(jrec[l]-irecmin) * 15; 

       for (i=0; i<15; i++) 
        nhdr[i] = nhdr1[indx1+i]; // nhdr1 is allocated before for rank>0! 

       MPI_Send(nhdr, 15, MPI_LONG, 0, l, MPI_COMM_WORLD); 
      } 
     } 

     free(nhdr); 

    } 

回答

4

沒有辦法保證你的消息按照他們從不同級別發送的順序到達0級。舉例來說,如果你有這樣的情況(S1指發送短信1):

rank 0 ---------------- 
rank 1 ---S1------S3--- 
rank 2 ------S2------S4 

不保證該信息會在訂單S1,S2,S3,S4的0級到達。 MPI做出的唯一保證是,每個等級的消息都在相同的通信器上發送,且具有相同的標籤(您正在執行的)將按照它們發送的相同順序到達。這意味着,爲了產生可能是:

S1, S2, S3, S4 

或者它可能是:

S1, S3, S2, S4 

或:

S2, S1, S3, S4 

...等等。

對於大多數應用程序來說,這並不重要。重要的順序是邏輯順序,而不是實時順序。你可以再看看你的應用程序,並確保你不能放鬆你的需求。

1

你是什麼意思「以相同順序收到的消息是他們發送的」?

在現在的代碼中,消息ARE(大體上)是以實際發送的順序接收的......但該順序與排名數字或其他任何內容無關。請參閱@Wesley Bland對此的迴應。

如果您的意思是「按排名順序接收郵件」......那麼有幾個選項。首先,像MPI_Gather或MPI_Gatherv這樣的集體將是一個「明顯的」選擇,以確保數據按產生它的排序進行排序。這隻適用於每個級別執行相同次數的迭代,並且這些迭代大致保持同步。

其次,您可以刪除MPI_ANY_SOURCE,並用「按順序」提供的緩衝區發佈一組MPI_IRevc。當消息到達時,它將自動地位於正確的緩衝區位置。對於收到的每條消息,都可以發佈新的MPI_Irecv,並提供正確的recv緩衝區位置。任何未匹配的MPI_Irecv都需要在作業結束時取消。

0

牢記的是:從給定的秩

  • 消息,以便接收和
  • 消息具有在通過MPI_RECV(返回的狀態結構(status.MPI_SOURCE))
始發處理器秩

您可以使用這兩個元素將接收到的數據正確放置到nhdr1中。