我问了同样的问题here,但我觉得它太长了所以我会以较短的方式再试一次:
我在主/从设置下使用Rocks群集上的最新OpenMPI获得了一个C ++程序。从设备执行任务,然后使用阻塞MPI_SEND / MPI_RECV调用(通过Boost MPI)将数据报告给主设备,该调用将数据写入数据库。主人目前明显慢于奴隶。我遇到了这个程序的问题,因为大约一半的奴隶卡在第一个任务上,从不报告他们的数据;使用strace / ltrace,似乎他们在MPI_SEND中卡住了轮询并且他们的消息永远不会被接收。
我编写了一个程序来测试这个理论(再次,在完整的here中列出)并且我可以引起类似的问题 - 从属通信显着减慢,因此他们执行的任务比他们应该的少 - 通过操纵速度使用睡眠的奴隶和主人。当速度(主)>速度(奴隶),一切正常。当速度(主)<速度(从站),每次都会对某些从站的消息造成明显延迟。
为什么会出现这种情况?
答案 0 :(得分: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
现在你停止所有工作,即使并非所有奴隶都报告了他们的数据并完成了多项任务。
当不同节点的网络连接高度不同时,会出现此问题。原因是在调用之后不处理发送和接收,而是如果这些功能中的两个能够进行某种握手,则进行通信。
作为解决方案,我建议:
希望这会有所帮助。