我是否需要为MPI :: Isend提供相应的MPI :: Irecv?

use*_*069 7 c mpi

一个看似愚蠢的问题,但我似乎无法找到一种确定的答案.

基本问题是我需要为MPI :: Isend提供相应的MPI :: Irecv吗?

也就是说,即使消息发送是非阻塞的,只要我在重新发送缓冲区之前等待发送完成,我是否需要使用非阻塞接收和等待接收发送的缓冲区?

我的观点是,我希望在发送消息时使用非阻塞发送来"执行其他操作"但接收器进程将立即使用缓冲区,因此我希望它们阻塞直到真正接收到缓冲区.

看起来我应该能够接收到MPI :: Recv的消息,即使它们是用MPI :: Isend发送的,但我想知道我是否遗漏了什么?

一点简单的伪代码

  if( rank == 0 ){
   int r;
   for ( int i = 0; i < n; i++ ){

     // DO SOME STUFF HERE...

     request.Wait(status);
     request2.Wait(status);
     request3.Wait(status);

     r = i;
     memcpy( key, fromKey(i), ...);
     memcpy( trace, fromTrace(i), ...);

     request  = MPI::COMM_WORLD.Isend( &r, 1, MPI::INT, node, tag );
     request2 = MPI::COMM_WORLD.Isend( key, 10, MPI::INT, node, tag );
     request3 = MPI::COMM_WORLD.Isend( trace, nBytesTotal, MPI::BYTE, node, tag );

     // DO SOME MORE STUFF HERE.

   }
   r = -1;
   request  = MPI::COMM_WORLD.Isend( &r, 1, MPI::INT, node, tag );

   // Carry on ...

  } else {

   int r = -1;
   MPI::COMM_WORLD.Recv( &r, 1, MPI::INT, 0, tag, status );
   while( r >= 0 ){

     MPI::COMM_WORLD.Recv( &key, 10, MPI::INT, 0, tag, status );
     memcpy( saveKey, key, ...);

     MPI::COMM_WORLD.Recv( &trace, nBytesTotal, MPI::BYTE, 0, tag, status );
     memcpy( saveTrace, trace, ...);

     MPI::COMM_WORLD.Recv( &r, 1, MPI::INT, 0, tag, status );
  }
Run Code Online (Sandbox Code Playgroud)

Hri*_*iev 16

不,您可以在通信的两端自由混合阻塞和非阻塞MPI操作.阻止与MPI调用何时将控制权返回给您的代码而不是对正在传输的消息的内容有关.

每条MPI消息都带有一个"信封",其中包含其源,目的地,标签和通信器.要成功接收消息,您的接收操作应仅与其信封匹配.信封绝不指定消息发送的确切程度 - 是通过阻塞,是通过非阻塞操作,是同步send(MPI_Ssend)还是缓冲(MPI_Bsend).唯一的例外是所谓的"就绪模式"发送,该发送使用MPI_Rsend()或者MPI_Irsend()要求已经发布匹配的接收操作或者不会传递消息.

这就是为什么术语"匹配接收操作"在整个MPI标准中使用而不是像"相应的接收功能"那样.