0

我在这里问了同样的问题,但我认为它太长了,所以我会以更短的方式再试一次:

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

我编写了一个程序来测试这个理论(同样,在这里完整列出),我可以通过使用睡眠来操纵从属和主控的速度,从而导致类似的问题 - 从属通信显着减慢,因此它们执行的任务比应有的要少。当速度(主)> 速度(从)时,一切正常。当 speed(master) < speed(slaves) 时,对于某些 slave 来说,消息每次都会显着延迟。

任何想法为什么会这样?

4

1 回答 1

1

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

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

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

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

更新 1:

让我们假设主人分发了他的数据。现在他等着奴隶们回来报告。当第一个奴隶报告回来时,他将首先发送他的 REPORTTAG,然后是他的 DONETAG。现在主人会给他送回一份新工作,如果

 currentTask < numtasks

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

 currentTask >= numtasks

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

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

作为解决方案,我建议:

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

希望这有帮助。

于 2011-10-20T01:02:39.523 回答