Я учусь использовать одностороннее общение в mpi4py. Чтобы проверить мое понимание, я придумал этот надуманный пример:
import mpi4py.MPI as mpi
import numpy as np
import time
def main():
rank = mpi.COMM_WORLD.Get_rank()
n_proc = mpi.COMM_WORLD.Get_size()
assert(n_proc == 2)
buff = np.zeros(10, dtype='d')
win = mpi.Win.Create(buff, 1, mpi.INFO_NULL, mpi.COMM_WORLD)
if (rank == 0):
win.Lock(1)
win.Put([buff, mpi.DOUBLE], 1)
win.Unlock(1)
buff[-1] = 9
time.sleep(30)
win.Lock(1)
win.Put([buff, mpi.DOUBLE], 1)
win.Unlock(1)
else:
holder = np.zeros(10)
failures = 0
while (holder[-1] != 9):
failures += 1
win.Lock(0)
win.Get([holder, mpi.DOUBLE], 0)
win.Unlock(0)
print('Took', failures, 'dials')
if __name__=='__main__':
main()
Я ожидаю, что это будет работать следующим образом: ранг 0 будет ждать 30 секунд, прежде чем поместить ndarray, содержащий [0, 0, ..., 0, 9]
, в общую память. Между тем, ранг 1 будет постоянно проверять, обновил ли ранг 0 свою совместно используемую память - когда это произойдет, он напечатает то, что видит. В частности, Я бы ожидал, что ранг 1 будет выполнять свой цикл while много раз в течение 30 секунд ожидания, пока ранг 0 не используется. Однако, когда я запускаю этот код с mpirun -n 2 python mwe.py
, я последовательно получаю этот вывод:
Took 2 dials
, указывающий, что вызов Get
произошел только дважды.
Конкретный вопрос: Почему только два звонка Get
с ранга 1?
Более расплывчатый вопрос: Я делаю очевидные ошибки в этом MWE? Я довольно новичок в mpi4py / MPI в целом.