MPI:使用阻塞发送和接收有什么好处?

MPI: what are the advantages of using blocking Send and Recv?

既然MPI也实现了iRecv和iSend,那么使用Send和Recv有什么好处,它们会阻塞程序的执行,从而导致性能下降?

有问题:mpi: blocking vs non-blocking

他们写

"Blocking communication is used when it is sufficient, since it is somewhat easier to use. Non-blocking communication is used when necessary, for example, you may call MPI_Isend(), do some computations, then do MPI_Wait(). This allows computations and communication to overlap, which generally leads to improved performance."

但是 "it is sufficient" 和 "it is necessary" 是什么意思?

有时在 Send 或 Recv 操作完成之前(在当前线程中)您无事可做 - 例如,您需要 Recv 的结果用于下一个操作。

在这种情况下,使用阻塞 Recv 是最好的选择,并且比使用 iRecv 然后等待更好。

如果您有事要做 - 例如,您正在发送上一个结果并同时计算下一个结果,那么非阻塞操作会更快,因为您不必等待。

基本上 - 如果在通信正在进行时您除了通信之外还有其他事情要做,阻塞只会降低性能,否则阻塞是等待的最高性能方式(由于共享缓冲区,等待代码内部可能的优化等)。 )

首先,您需要记住,正确的 MPI 应用程序不应期望在匹配的接收被发布之前阻塞发送(例如 MPI_Send())returns。比如两个task需要交换数据,这样是不正确的

MPI_Send(...);
MPI_Recv(...);

因为它可能会死锁。 一个选项是手动订购通讯

if (peer < me) {
    MPI_Send(...);
    MPI_Recv(...);
} else {
    MPI_Recv(...);
    MPI_Send(...);
}

恕我直言,这使得应用程序更难编写和维护。

另一种选择是使用非阻塞通信,这样您就不必再担心死锁了。

MPI_Isend(...);
MPI_Irecv(...);
MPI_Waitall(...);

注意这个简单的例子说明了一个更普遍的问题,MPI_Sendrecv() 应该是首选。

一些 MPI 库实现了一个带有一些互连的进度线程。 (请记住,大多数情况下不会,但这有望改变)。 在这种情况下,可以使用非阻塞通信来重叠计算和通信,从而使应用程序更加高效。

MPI_Irecv(...);
// perform some computation that do no require the data to be received
MPI_Wait(...);

如果您的 MPI 库未实现进度线程,则在调用 MPI_Wait() 之前不会开始接收任何消息。

并非所有应用程序都能(简单地)受益于重叠计算和通信。在这种情况下

MPI_Recv(...);

不仅更紧凑,而且可能比非阻塞对应物更高效,因为与

相比,它为 MPI 库的优化留出了额外的空间
MPI_Irecv(...);
MPI_Wait(...);

归根结底,阻塞并不比非阻塞好,反之亦然。也就是说,根据具体情况,一个通常比另一个更合适。