c++ - MPI 是否丢弃或延迟消息?

标签 c++ mpi openmpi

我问了同样的问题here ,但我觉得它太长了,所以我会用更短的方式再试一次:

我在主/从设置下的 Rocks 集群上有一个使用最新 OpenMPI 的 C++ 程序。从站执行任务,然后使用阻塞 MPI_SEND/MPI_RECV 调用(通过 Boost MPI)向主站报告数据,主站将数据写入数据库。主人目前明显比奴隶慢。我的程序有问题,因为大约一半的奴隶卡在第一个任务上,从不报告他们的数据;使用 strace/ltrace,他们似乎卡在 MPI_SEND 中进行轮询,并且永远不会收到他们的消息。

我写了一个程序来测试这个理论(同样,完整列出 here )我可能会导致类似的问题 - 从属通信显着减慢,所以他们做的任务比他们应该做的少 - 通过操纵从属的速度和主人使用 sleep 。当 speed(master) > speed(slaves) 时,一切正常。当 speed(master) < speed(slaves) 时,消息每次都会对某些从属设备显着延迟。

知道为什么会这样吗?

最佳答案

据我所知,这是主节点 while 循环中 recv 的结果。

 ...
 while (1) {
 // Receive results from slave.
      stat = world.recv(MPI_ANY_SOURCE,MPI_ANY_TAG);
 ...

当有来自一个从节点的消息时,主节点在 while 循环内的代码完成之前无法收到任何消息(这需要一些时间,因为存在 sleep ),因为主节点没有并行运行。因此,在第一个从站完成发送消息之前,所有其他从站都不能开始发送他们的消息。然后下一个从站可以开始发送消息,但随后所有其他从站都将停止,直到执行 while 循环内的代码。

这会导致您看到的行为,即从站通信非常慢。为避免此问题,您需要实现点对点通信非阻塞或使用全局通信。

更新 1:

让我们假设主人分发了他的数据。现在他等到奴隶们返回。当第一个从机返返回告时,他将首先发送他的 REPORTAG,然后是他的 DONETAG。

 currentTask < numtasks

现在奴隶们又开始了他的计算。现在的情况可能是,在他完成之前,主人只能处理另一个奴隶。因此,开始的奴隶现在再次首先发送他的 REPORTAG,然后发送他的 DONETAG,并获得一份新工作。当这种情况持续下去时,最终只有 2 个奴隶找到了新工作,其余的则无法完成他们的工作。所以在某些时候这是真的:

 currentTask >= numtasks

现在你停止了所有的工作,即使不是所有的奴隶都报告了他们的数据并且完成了不止一项任务。

当不同节点的网络连接差异很大时,最容易出现此问题。原因是发送和接收在它们的调用之后没有被处理,相反,如果这些函数中的两个能够进行某种握手,通信就会发生。

作为解决方案,我建议:

  • 在杀死所有作业之前确保所有奴隶都已完成
  • 使用 gather 和 scatter 代替消息,然后在每个任务后同步所有 slaves。
  • 如果消息不是很大,则使用缓冲或非缓冲发送和接收操作。确保您没有在 Master 上遇到内存溢出
  • 从主/从更改为更并行的工作模式,例如将所有任务分配给两个节点,然后将任务进一步从这些节点分配到下两个节点,依此类推。最后就这样把任务送回去。该解决方案可能还具有通信成本仅为 O(logn) 而不是 O(n) 的优势。

希望这对您有所帮助。

关于c++ - MPI 是否丢弃或延迟消息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7829921/

相关文章:

c++ - 使用 CBOR 编码和解码时出现问题

c++ - C++:为什么这可以加快我的代码的速度?

c++ - MPI 多次发送和接收

mpi - OpenMPI 和 MPICH2 是否兼容?

c - 使用 MPI_Send 发送矩阵的多列

segmentation-fault - 使用电子围栏时 Openmpi 段错误

c++ - 错误:使用已删除的函数 std::basic_ofstream(OpenCV 和 C++11)

c - 使用 openmpi 初始化一个数组一次

c++ - MPI_Barrier 无法正常运行

c++ - float 乘以零是否保证产生零?