2014-01-29 27 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中。