由于MPI也实现了iRecv和iSend,使用Send和Recv有什么好处,它会阻止程序的执行,从而导致性能下降?
问题:mpi: blocking vs non-blocking
他们写了"当它足够时使用阻止通信,因为它更容易使用。必要时使用非阻塞通信,例如,您可以调用MPI_Isend(),进行一些计算,然后执行MPI_Wait()。这允许计算和通信重叠,这通常会导致性能提高。"
但它意味着什么"它就足够了#34;和"这是必要的"?
答案 0 :(得分:2)
首先,您需要记住正确的MPI应用程序不应期望在发布匹配的接收之前发送阻塞发送(例如MPI_Send()
)。例如,如果两个任务需要交换数据,那么
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(...);
底线,阻挡并不比非阻塞更好,反之亦然。话虽如此,根据具体情况,一个通常比另一个更合适。
答案 1 :(得分:1)
在Send或Recv操作完成之前,有时您没有其他事情要做(在当前线程中) - 例如,您需要Recv的结果用于下一步操作。
在这种情况下,使用阻止Recv是最好的选择,并且比使用iRecv然后等待更好。
如果您有事情要做 - 例如您发送的是上一个结果,同时计算下一个结果,那么非阻塞操作会更快,因为您不必等待。
基本上 - 阻塞只会降低性能,如果在通信进行过程中除了通信之外还有其他内容,否则阻塞是最高性能的等待方式(由于共享缓冲区,等待代码中可能的优化等)< / p>