当在Windows 10的MSMPI上使用MPI4PY 3.0.0在Python 3.7.0中实现并行算法时,我遇到了Gatherv无法收集所有内容的问题...当检查各种位的打印时,似乎正在执行错误的顺序。
我写了一些重复这个问题的代码:
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()
的用法,还是我的环境有问题?
答案 0 :(得分:2)
它们似乎以错误的顺序打印的原因是由于MPI后端收集消息。所有子进程的标准输出流都没有直接连接到终端窗口,因为这在多台计算机上是不可能的。
相反,MPI后端正在收集每个进程的所有消息。然后,它使用标准MPI调用在等级0的后端收集这些消息。正是在这种通信中,消息的顺序变得混乱。
通常,在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。因此,存在一个竞争条件,该竞争条件从根本上决定了事物的打印顺序。因此,为了使事情按正确的顺序进行,您需要将同步调用和睡眠调用结合使用,以便不经常调用刷新事件,从而避免出现竞争情况。
我怀疑您正在发生的事情是仅在过程结束时才刷新输出。由于它是同时发生在所有流程中的,所以您所看到的就是这场沟通竞赛的结果。
我希望有帮助。