mpi:阻止与非阻止

我无法理解在MPI中阻塞通信和非阻塞通信的概念。 两者有什么区别? 有什么优点和缺点?

谢谢!

阻塞通信使用MPI_Send()MPI_Recv() 。 这些function不会返回(即阻塞),直到通讯完成。 简化一下,这意味着传递给MPI_Send()的缓冲区可以被重用,因为MPI将它保存在某个地方,或者因为已经被目的地接收了。 同样, MPI_Recv()在接收缓冲区填充有效数据时返回。

相反,使用MPI_Isend()MPI_Irecv()完成非阻塞通信。 即使通信尚未完成,这些函数立即返回(即,它们不阻止)。 您必须调用MPI_Wait()MPI_Probe()来查看通信是否完成。

阻塞通信在足够的时候被使用,因为使用起来更容易。 必要时使用非阻塞通信,例如,您可以调用MPI_Isend() ,做一些计算,然后执行MPI_Wait() 。 这允许计算和通信重叠,这通常导致改进的性能。

请注意,集体通信(例如,all-reduce)仅在其阻塞版本中可用,直到MPIv2。 IIRC,MPIv3引入了无阻塞的集体通信。

在使用阻塞通信时,你必须关心发送和接收呼叫,例如看这个代码

  if(rank==0) { MPI_Send(x to process 1) MPI_Recv(y from process 1) } if(rank==1) { MPI_Send(y to process 0); MPI_Recv(x from process 0); } 

在这种情况下会发生什么?

  1. 进程0将x发送到进程1并阻塞,直到进程1接收到x为止。
  2. 进程1发送y到进程0并阻塞,直到进程0接收到y,但是
  3. 进程0被阻塞,使得进程1阻塞无限,直到两个进程被终止。

这很容易。

非阻塞意味着计算和传输数据可以同时发生在单个进程中。

Blocking意味着你的好友,你必须确保你已经完成了数据的传输,然后回到完成下一个命令,这意味着如果有一个传输,然后计算,计算必须在传输成功之后。

这个post虽然有点老,但是我主张接受的答案。 语句“这些函数在通信完成之前不会返回”有点误导,因为阻塞通信不能保证在发送和接收操作之间握手。

阻塞通信 :阻塞并不意味着消息被传送到接收器/目的地。 它只是意味着缓冲区可用于重用。 要重新使用缓冲区,将信息复制到另一个内存区就足够了,也就是说,库可以将缓冲区数据复制到库中自己的内存位置,然后对于例如MPI_Send可以返回。 对于MPI_Recev同样,如果来自接收缓冲区的数据被复制到另一个内存位置,MPI_Recv可以返回。

在这种阻塞调用期间发生的情况是计算被暂停,直到被阻塞的缓冲区被释放。 这通常会导致计算资源的浪费,因为Send / Recv通常将数据从一个存储单元复制到另一个存储单元,而cpu中的寄存器保持空闲状态。

如果MPI_Send发送的消息很小,则可以将数据复制到系统缓冲区,即MPI库通常有足够的空间将消息缓冲区复制到自己的缓冲区中。 但是,如果消息太大而无法复制到库缓冲区(在分布式系统上运行的实际问题就是这种情况),MPI_Send将被阻塞,直到发送缓冲区的数据被传送到接收缓冲区为止,并且这种实现保证MPI_Send和MPI_Recv的握手,即MPI_Send是否保证MPI_Recv通常是问题和实现依赖。

非阻塞通信:对于非阻塞通信,应用程序为发送和/或接收创build一个通信请求,并取回一个句柄,然后终止。 这就是保证执行过程所需要的一切。 即MPI库被通知必须执行该操作。

对于发送方来说,这允许与通信重叠计算。

对于接收方来说,这允许重叠一部分通信开销,即将消息直接复制到应用程序中接收方的地址空间。