I am trying to let rank 0 get other rank indexes, but I got different results from MPI.Irecv!() and MPI.Recv() , and result from MPI.Irecv!() seems odd:
import MPI
function main()
MPI.Init()
comm = MPI.COMM_WORLD
size = MPI.Comm_size(comm)
rank = MPI.Comm_rank(comm)
if rank==0
buf = 10
mid = [10]
for i in 1:size-1
MPI.Recv!(mid, i, 0, comm)
println("mid: $mid")
buf = mid[1]
println("buf: $buf")
end
else
MPI.Isend([rank], 0, 0, comm)
end
MPI.Finalize()
end
main()
Which outputďź
mid: [1]
buf: 1
mid: [2]
buf: 2
mid: [3]
buf: 3
If I replace MPI.Recv!(mid, i, 0, comm) by MPI.Irecv!(mid, i, 0, comm) , the output seemed not right:
So my question is, why mid didnât change when I use MPI.Irecv!(), and how to get the right rank number with MPI.Irecv!()?
Thanks for any suggestions and answers!
MPI.Irecv! is a non-blocking operation, that is, it returns immediately without waiting for the operation to complete. So by the time you call println(mid), data in mid has not been yet updated since the data has not been yet received.
Unlike its blocking variant (MPI.Recv!), MPI.Irecv! returns a ârequestâ. At some point of your code, you need to wait for this request to complete, before you can operate on the received data. In your specific case, you want to do the following:
for i in 1:size-1
req = MPI.Irecv!(mid, i, 0, comm)
MPI.Wait!(req) # wait for operation to complete
println("mid: $mid")
buf = mid[1]
println("buf: $buf")
end
Note that all of this also applies to MPI.Isend, which is also non-blocking.
Note that buf is immutable (itâs an Int), which is why you canât pass it directly to Irecv! as a buffer.
When you wrap it in an array, as in [buf], youâre passing Irecv! a single-element array. That function then replaces buf by the received value. Note that the array is being modified, not buf itself (which, again, is immutable). In your last bit of code, youâre losing the received information since the array is anonymous. Thatâs why you need to attach the array to a variable (like mid in your previous code).