MPI4Py comm.Barrier() 没有阻塞 MSMPI?

MPI4Py comm.Barrier() not blocking on MSMPI?

在 Python 3.7.0 中使用 MPI4PY 3.0.0 在 Windows 10 上的 MSMPI 上实现并行算法时,我遇到了 Gatherv 没有收集所有内容的问题...当 cheking 打印时各种位似乎以错误的顺序执行事情。

我写了一些重复问题的代码:

from mpi4py import MPI
from time import sleep
import random

comm = MPI.COMM_WORLD
rank = comm.Get_rank()


if rank == 0:
    sleep(2)
    print("head finished sleeping")

comm.Barrier()

sleep(random.uniform(0, 2))
print(rank, 'finished sleeping ')

comm.Barrier()

if rank == 0:
    print("All done!")

如果我理解 comm.Barrier() 正确,这应该会产生

head finished sleeping
2 finished sleeping
0 finished sleeping
3 finished sleeping
1 finished sleeping
4 finished sleeping
All done!

中间位按某种顺序排列,对吗?但是当我实际上 运行 mpiexec -n 5 python .\blocking_test.py 我得到如下:

2 finished sleeping
1 finished sleeping
3 finished sleeping
head finished sleeping
0 finished sleeping
All done!
4 finished sleeping

是我理解错了comm.Barrier()的用法,还是我的环境有问题?

它们似乎以错误的顺序打印的原因是因为收集消息的 MPI back-end。所有子进程的标准输出流都没有直接连接到终端window,因为这不可能跨多台计算机。

相反,MPI back-end 正在收集来自每个进程的所有消息。然后,它使用标准 MPI 调用在等级 0 的 back-end 中收集这些消息。正是在这种通信中,消息的顺序变得混乱。

通常,标准输出在 MPI 进程中不被优先处理,因此以正确的顺序打印输出几乎没有影响。通常,输出保存在 运行 进程的输出缓冲区中。只有在发生以下事件时才会打印输出(可能更多):

  1) The end of the process
  2) When there is a buffer over-flow (i.e. large amount of data is printed to the output)
  3) flush is called on the output buffer (i.e. 'sys.stdout.flush()')

所以您可以通过在打印时刷新标准输出来帮助自己:

  1) print('my message'); sys.stdout.flush()
  2) print('my message on newer version of python', flush=True)

然而,在实践中很难让它正常工作。如果多个 MPI 进程同时发生刷新事件。然后多个进程将发送消息到排名 0。因此,存在一个竞争条件,它本质上决定了打印内容的顺序。因此,为了以正确的顺序处理事情,您需要混合使用同步和睡眠调用,这样刷新事件的调用频率就足以避免竞争条件。

我怀疑您遇到的情况是输出仅在流程结束时才被刷新。既然它同时发生在所有进程上,那么你看到的就是这次通信竞赛的结果。

希望对您有所帮助。