关于MPI Non-blocking details based on standard的问题

Questions about MPI Non-blocking details based on standard

所以最近,我一直在研究开发一些异步算法。我正在做一些并行性能研究,我一直怀疑我没有正确理解各种非阻塞 MPI 函数的一些细节。

我在这里看到了一些有见地的 post,即:

有几件事我不确定或者只是想澄清一下与使用非阻塞功能相关的事情,我认为这些事情可能会帮助我提高当前软件的性能。

来自 MPI 3.0 标准的 非阻塞通信 部分:

A nonblocking send start call initiates the send operation, but does not complete it. The send start call can return before the message was copied out of the send buffer. A separate send complete call is needed to complete the communication, i.e., to verify that the data has been copied out of the send buffer. With suitable hardware, the transfer of data out of the sender memory may proceed concurrently with computations done at the sender after the send was initiated and before it completed.

...

If the send mode is standard then the send-complete call may return before a matching receive is posted, if the message is buffered. On the other hand, the receive-complete may not complete until a matching receive is posted, and the message was copied into the receive buffer.

因此,作为关于 MPI_Isend(以及类似的 MPI_Irecv)的第一组问题,似乎要确保非阻塞发送完成,我需要使用某种机制来 检查它是完整的,因为在最坏的情况下,可能没有合适的硬件来同时传输数据,对吗?因此,如果我从不在非阻塞发送之后使用 MPI_TestMPI_Wait 之类的东西,那么 MPI_Isend 可能永远不会真正发出消息,对吗?

这个问题适用于我的一些工作,因为我通过 MPI_Isend 发送消息并且在收到预期的响应消息之前不会实际测试完整性,因为我想避免 MPI_Test 的开销电话。虽然这种方法一直有效,但根据我的阅读,它似乎是错误的。

此外,第二段似乎是说对于标准的非阻塞发送,MPI_Isend,它可能不会甚至开始发送任何数据,直到目标进程调用了匹配的接收。鉴于 MPI_Probe/MPI_Iprobe 的可用性,这是否意味着 MPI_Isend 调用将 至少 发送消息的一些初步元数据,例如大小、源和标记,以便目标进程上的探测功能可以知道要将消息发送到那里,因此目标进程实际上可以 post 相应的接收?

相关的是关于探测器的问题。在 Probe and Cancel 部分,标准说

MPI_IPROBE(source, tag, comm, flag, status) returns flag = true if there is a message that can be received and that matches the pattern specifed by the arguments source, tag, and comm. The call matches the same message that would have been received by a call to MPI_RECV(..., source, tag, comm, status) executed at the same point in the program, and returns in status the same value that would have been returned by MPI_RECV(). Otherwise, the call returns flag = false, and leaves status undefined.

从上面的段落开始,很明显探测会告诉你是否有一条可用消息可以接收到对应于指定的 sourcetagcomm .我的问题是,您是否应该假设成功探测的相应发送数据实际上尚未传输?

在阅读了标准之后,我现在看来是合理的,探测器知道的消息确实不一定是本地进程实际上已经完全接收到的消息。鉴于先前关于标准非阻塞发送的详细信息,似乎您需要 post 在进行探测后接收以确保源非阻塞标准发送将完成,因为有时源可能是发送 MPI 不想复制到某个内部缓冲区的大消息,对吗?无论哪种方式,似乎 post 在探测之后接收接收是确保您实际从相应的发送中获取完整数据的方式。这是正确的吗?

后一个问题与我的代码中的一个实例有关,在该实例中我正在执行 MPI_Iprobe 调用,如果成功,我将执行 MPI_Recv 调用以获取消息。但是,我认为现在这可能会有问题,因为我在想如果探测成功,那就意味着它已经得到了全部信息。这对我来说意味着 MPI_Recv 会很快 运行,因为完整的消息已经在本地内存中的某个地方。但是,我觉得这是一个不正确的假设,现在对它进行一些澄清会有所帮助。

MPI 标准不要求进度线程。这意味着 MPI_Isend() 可能在通信进行之前什么都不做。大多数 MPI 子例程在幕后发生进展,MPI_Test()MPI_Wait()MPI_Probe() 是最明显的。

恐怕您正在混合进度和同步发送(例如 MPI_Ssend())。

MPI_Probe()是一个本地操作,这意味着它不会联系发件人并询问是否发送了一些东西,也不会处理它。

性能方面,您应该尽可能避免意外消息,这意味着接收应该在另一端发送消息之前先在一端发布。

性能和便携性之间存在 trade-off:

  • 如果你想编写可移植的代码,那么你不能假设有一个 MPI 进度线程
  • 如果您想在给定系统上优化您的应用程序,您应该尝试在您正在使用的互连上实现进度线程的 MPI 库

请记住大多数 MPI 实现(阅读这不是 MPI 标准强制要求的,您不应该依赖它)以急切模式发送小消息。 这意味着如果消息足够小,MPI_Send() 可能会立即 return(并且足够小取决于您的 MPI 实现、如何调整或使用哪种互连)。