MPI4Py comm.Barrier() не блокируется на MSMPI?
При реализации параллельного алгоритма в Python 3.7.0 с использованием MPI4PY 3.0.0 в MSMPI в Windows 10 у меня были проблемы с тем, что 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 ответов
Причина, по которой они кажутся напечатанными в неправильном порядке, связана с серверной частью 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. Таким образом, существует состояние гонки, которое по существу диктует порядок, в котором печатаются вещи. Итак, чтобы все было в правильном порядке, вам необходимо применить сочетание вызовов синхронизации и сна, чтобы события сброса вызывались достаточно редко, чтобы избежать состояния гонки.
Я подозреваю, что с вами происходит то, что вывод сбрасывается только в конце процесса. Поскольку это происходит со всеми процессами одновременно, то то, что вы видите, является результатом этой гонки общения.
Надеюсь, это поможет.