mpi4py Send/Recv with tag
Question: How can I pass a the rank of a process as a tag to the
mpi4py.MPI.COMM_WORLD.Send() function and correctly receive it with
mpi4py.MPI.COMM_WORLD.Recv()?

I'm referring to the following code example for [sending and receiving
messages between two processes using Send and Recv
functions](http://jeremybejarano.zzl.org/MPIwithPython/pointToPoint.html)

    
    
    #passRandomDraw.py
    import numpy
    from mpi4py import MPI
    comm = MPI.COMM_WORLD
    rank = comm.Get_rank()
    
    randNum = numpy.zeros(1)
    
    if rank == 1:
        randNum = numpy.random.random_sample(1)
        print "Process", rank, "drew the number", randNum[0]
        comm.Send(randNum, dest=0)
    
    if rank == 0:
        print "Process", rank, "before receiving has the number", randNum[0]
        comm.Recv(randNum, source=1)
        print "Process", rank, "received the number", randNum[0]
    

I want to pass the rank of the sending process as a tag so that the receiving
process can identify it in case there are multiple senders. This is what I do

    
    
    #passRandomDraw.py
    import numpy
    from mpi4py import MPI
    comm = MPI.COMM_WORLD
    rank = comm.Get_rank()
    
    randNum = numpy.zeros(1)
    rnk = -1 # EDIT
    
    if rank == 1:
        randNum = numpy.random.random_sample(1)
        print "Process", rank, "drew the number", randNum[0]
        comm.Send(randNum, dest=0, tag=rank) # EDIT
    
    if rank == 0:
        print "Process", rank, "before receiving has the number", randNum[0]
        print "Sender rank:", rnk
        comm.Recv(randNum, 1, rnk) # EDIT
        print "Process", rank, "received the number", randNum[0]
        print "Sender rank:", rnk # EDIT
    

I expect the value of rnk to be 1 for the receiving process (which has
rank=0), but it is still -1.

Can someone tell me what I'm doing wrong here? Thanks!


Answer: The function `Recv` will store a received message inside a variable. You have
to supply the rank of the expected sender. Thus you always know who the sender
is. A message passing interface does never need to identify someone, that
information is always intrinsic to the system.

If you expect multiple message from the same sender you can distinguish these
using tags. You need to supply these tags yourself, there is no natural way to
obtain these. Just label the messages somehow, number them.

If you have a tag, the `Recv` function will only return when a message has
been received which has a fitting source **and** tag. This is a blocking
function call.

In your case, `tag=-1` is equal to the universal constant `MPI.ANY_TAG`
(verify via `print MPI.ANY_TAG`) and thus the `Recv` will accept any tag. But
it will in no way overwrite its input variable `rnk`. Try `rnk = -2 # EDIT`
and you'll see.

You can write your code differently, though this will not change the
underlying logic (i.e. you as a programmer must always know the sender) it
just hides it, makes it implicit:

    
    
    #passRandomDraw.py
    import numpy
    from mpi4py import MPI
    comm = MPI.COMM_WORLD
    rank = comm.Get_rank()
    
    randNum = numpy.zeros(1)
    rnk = -1 # EDIT
    
    if rank == 1:
        randNum = numpy.random.random_sample(1)
        print "Process", rank, "drew the number", randNum[0]
        comm.Send(randNum, dest=0, tag=rank) # EDIT
    
    if rank == 0:
        print "Process", rank, "before receiving has the number", randNum[0]
        print "Sender rank:", rnk
        status = MPI.Status()
        comm.Recv(randNum, source=MPI.ANY_SOURCE, tag=MPI.ANY_TAG, status=status) # EDIT
        rnk = status.Get_source()
        print "Process", rank, "received the number", randNum[0]
        print "Sender rank:", rnk # EDIT
    

