I'm learning how to use one-sided communication in mpi4py. To test my understanding, I came up with this contrived example:
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()
I expect this to work as follows: rank 0 will wait for 30 seconds before placing the ndarray containing [0, 0, ..., 0, 9] into the shared memory. Meanwhile, rank 1 will continuously check to see if rank 0 has updated its shared memory---once it has, it will print out what it sees. Specifically, I would expect that rank 1 would execute its while loop many many times during the 30 second wait while rank 0 is idle. However, when I run this code with mpirun -n 2 python mwe.py, I consistently get this output:
Took 2 dials
indicating that the call to Get only happened twice.
Specific question: Why are there only two calls to Get from rank 1?
More vague question: Am I making an obvious mistakes in this MWE? I am pretty new to mpi4py/MPI in general.