非阻塞 MPI 和会合协议

Posted

技术标签:

【中文标题】非阻塞 MPI 和会合协议【英文标题】:Nonblocking MPI and rendezvous protocol 【发布时间】:2022-01-02 08:56:39 【问题描述】:

我不完全理解 MPI 的非阻塞通信和集合协议应该如何交互。

首先,考虑这个伪代码,它在使用集合协议时会阻塞(假设我们有 2 个进程):

if (rank == 0) 
    MPI_Send (big_message, destination=1)
    MPI_Recv(source=1)
 else 
    MPI_Send(big_message, destination=0)
    MPI_Recv(source=0)

当消息太大而无法放入内部缓冲区时,这显然会阻塞,因为两个进程中的MPI_Sends 将等待发布匹配的接收。

在我的系统上,我发现以下修改可以工作:

if (rank == 0) 
    MPI_Isend (big_message, destination=1, &request)
    MPI_Recv(source=1)
    MPI_Wait(request)
 else 
    MPI_Isend(big_message, destination=0, &request)
    MPI_Recv(source=0)
    MPI_Wait(request)

我们使用非阻塞通信来发送消息。我的解决方案对 MPI 的每个实现都是正确的吗?我已经读过,当调用MPI_Isend 时,并没有强制要求实现启动任何形式的通信,并且可以在调用MPI_Wait 时执行它。这样的实现会破坏我的代码吗?我的理解是,在这种情况下,MPI_Isend 基本上是无操作的,并且对于我的代码,两个进程都会在MPI_Recv 中等待未发送的发送。

如果我的伪代码不可移植,有没有办法使用非阻塞通信来修复它?

【问题讨论】:

您的解决方案是正确的,更好的解决方案是使用MPI_Sendrecv()。在后台,保证在MPI_Recv() 期间进行(足够的)通信(例如发送消息),这就是第二个版本永远不会挂起的原因。 【参考方案1】:

说所有通信都可以在等待调用时发生是一种简单的观点,并且可能只有在所有通信都是非阻塞的情况下才是正确的。严格来说,这意味着您的代码将在阻塞接收上死锁,因为发送将发生在它们之后。这不会发生。

对于您的情况,标准的第 3.7.4 节说“[...] 对 MPI_Wait 的调用完成发送,如果匹配的接收已经开始,最终将返回 [...一些注释。 ..]" 所以,是的,你的代码是正确的。

【讨论】:

以上是关于非阻塞 MPI 和会合协议的主要内容,如果未能解决你的问题,请参考以下文章

MPI 非阻塞发送/接收

MPI 非阻塞发送和接收排序

发送多个 mpi 非阻塞发送 - 它会保留发送的顺序吗

连续 MPI 非阻塞调用

一个不安全的 MPI 非阻塞通信示例?

用于未知消息大小的 MPI 非阻塞发送和接收以及 mpi_iprobe()