1

我有一段 MPI C 代码,如下所示:

for(i=0;i<NTask;i++)
{
  got_initial_bit_of_data[i]=0;
  if(need_to_communicate with i)
     MPI_ISend(&bit_of_pre_data_for_i,1,MPI_INT,partner,0,MPI_COMM_WORLD,&pre_requests[i]);
}
while(1)
{
  MPI_Testsome(NTask,pre_requests,&ndone,idxs,MPI_STATUSES_IGNORE)
  if(ndone)
  {
    for(i=0;i<ndone;i++)
    {
      MPI_ISend(&the_main_block_of_data_for_i,size_of_block,MPI_BYTE,idxs[i],1,MPI_COMM_WORLD,&main_requests[idxs[i]]);
    }
  }
  //Other stuff that doesn't matter
  MPI_IProbe(MPI_ANY_SOURCE,0,MPI_COMM_WORLD,&flag,&status);
  if(!flag)
  {
    MPI_IProbe(MPI_ANY_SOURCE,1,MPI_COMM_WORLD,&flag,&status);
  }
  if(flag)
  {
    //Receiving the initial little bit of data
    if(status.MPI_TAG==0)
    {
      //Location 1
      got_initial_bit_of_data[status.MPI_SOURCE]=1;
      MPI_Recv(&useful_location,1,MPI_INT,status.MPI_SOURCE,MPI_STATUS_IGNORE);
    }
    //Receiving the main bit of data
    else if(status.MPI_TAG==1)
    {
      //Location 2
      if(got_initial_bit_of_data[status.MPI_SOURCE]!=1)
        //Something has gone horribly wrong...
      //Receive the main bit of data here...
    }
  }
}

显然我省略了很多细节,因为完整的代码有几百行。如果我所做的某些事情看起来有点奇怪,那可能是因为省略了代码块中的某些内容。

这个想法是,在开始时,每个处理器都会向它想要与之交谈的那些处理器发送一个“公告”消息。当它检测到那些处理器已收到此消息时(即当 MPI_Testsome 指示“公告”MPI_Isend 完成时),它应该发送一大块数据。

从处理器接收数据的角度来看,它应该首先在位置 1 接收到公告消息,这将导致 MPI_Testsome 指示 Isend 完成并发送大块数据。然后接收处理器应该在位置 2 接收主数据块。按照这个逻辑,当 got_initial_bit_of_data[status.MPI_SOURCE] 为 0 时应该不可能到达位置 2,但这正是偶尔会发生的情况,我会喜欢找出原因。

要么我的代码逻辑错误,要么我缺少一些 IProbe 和 Testsome 的微妙之处。

我还退出并重新输入了这整个代码块,不同的处理器在不同的时间点进出,但只有在它们的所有 ISend 都已处理后(由 Testsome 确定它们已完成)。

如果上述解释没有任何意义,我想知道的是在任何情况下Testsome声称在没有匹配接收完成(甚至开始)的情况下完成了ISend?例如,处理器对 IProbe 的调用是否足以让 Testsome 认为请求已完成?

4

1 回答 1

3

如果上述解释没有任何意义,我想知道的是在任何情况下Testsome声称在没有匹配接收完成(甚至开始)的情况下完成了ISend?例如,处理器对 IProbe 的调用是否足以让 Testsome 认为请求已完成?

MPI_Testsome 的所有保证是 MPI 不再需要您从 ISend 使用的缓冲区。如果要保证接收方已经开始接收,请使用同步形式 ISSend。

于 2013-09-25T16:40:06.960 回答