Click here to go to the TACC Home Page

TACC

Standard Send and Receive

The standard send subroutine, mpi_send, sends data to a specific process identified by the idest argument. The rank of the destination processor (idest) must be within the context of the communicator icomm -- that is, a group member of the communicator. The tag number is an integer that you define.

call mpi_send (data, icount, itype, idest, itag, icomm, ierr)
   Message-Passing Interface
where:

Parameter Description Status
idest rank of destination processor [IN]
itag message tag (identifier) [IN]
icomm send message in this context [IN]

The standard send call does not return until the data area is free to be overwritten. Many MPI implementations have local buffers to expedite the return: if the data and its associated message envelope can be immediately stored for safe keeping in the buffer, the send call returns immediately and the rest of the communication continues "behind the scenes". If there is insufficient buffer space to pack the message, the send subroutine waits until a receive subroutine in process idest accepts the send. In summary, mpi_send safeguards the message data from being overwritten and the send may wait until an accepting receive is posted if insufficient space is available to buffer the message.

The standard receive subroutine, mpi_recv, has arguments identical to the default send routine except for the additional integer message-status array and the substitution of a source variable for a destination variable.

Note: both isrc and itag are input variables, and they must match sender values on entry into the subroutine. They are not output variables.

The receive routine will wait until a message arrives and is completely transferred to the data location. Call it with this syntax:

call mpi_recv(data, icount, itype, isrc, itag, icomm, istatus, ierr)

where:

Parameter Description Status
isrc receive from this rank (process); use MPI_ANY_SOURCE to receive from any process within the context specified by icomm [IN]
itag receive the data if the sender's tag has this value (use MPI_ANY_TAG to receive message with any tag value) [IN]
icomm receive message from sender in this context [IN]
istatus message status array (of type integer) [OUT]

In a send/receive pair, the MPI data type and the communicator must match. Since the data count (icount) specifies the size of the receiver's data array in the receiving process, it should equal or exceed that of the sender's value or you run the risk of the receiver writing past the end of your data storage array. The parameters MPI_ANY_TAG and MPI_ANY_SOURCE may be used in the receiver to accept any tag and any source, respectively. Below is an example of send/receive pairs which pass an integer (message) around a ring of processes. Starting at process (rank) 0, the value "1" is passed to a neighbor process having a rank of one greater than the sender.

Explanation: The message status array is sized by the MPI_STATUS_SIZE parameter. Modulo functions determine the source and destination ranks for each process thus creating a ring of processes around which the message token proceeds. Process 0 sends an integer one to process 1, while all other processes post a receive and wait. In sequence, process 1 completes its receive and sends to process 2; next, process 2 completes its receive and sends to process 3; ...; process npes-1 completes its receive and sends to process 0; process 0 completes its receive and the ring passing is complete. The diagram at the end shows a convenient notation to make a time-line of events.

      Program sr
      include 'mpif.h'
      dimension istatus(MPI_STATUS_SIZE)
      iwcomm=MPI_COMM_WORLD
      call mpi_init(ierr)
C
      call mpi_comm_size(MPI_COMM_WORLD,npes, ierr)
      call mpi_comm_rank(MPI_COMM_WORLD,itask,ierr)
C
C       Send message around ring (0->1->2...NPES-1->0)
C
      ides = mod(itask+1,     npes)
      isrc = mod(itask+npes-1,npes)
C
C            Start Sending from task 0, and wait (recv) for count.
C
      if(itask.eq.0) then
        call mpi_send(1,1,MPI_INTEGER, ides,9,iwcomm, ierr)
        call mpi_recv(j,1,MPI_INTEGER, isrc,9,iwcomm, istatus,ierr)
      else
        call mpi_recv(j,1,MPI_INTEGER, isrc,9,iwcomm, istatus,ierr)
        i=j+1
        call mpi_send(i,1,MPI_INTEGER, ides,9,iwcomm, ierr)
      endif
C
      if(itask.eq.0) print*,'I counted ',j,' processors'
      call mpi_finalize(ierr)
      end

******Sequence of events for processes 0,1,...,j,k.

      Event  Time -->
      |
      V

      0->1	k)-0									k->)-0
      0)-1	0->)-1, 1->2
      1)-2			1->)-2, 2->3
      2)-3					2->)-3, 3->4
...				...
      j)-k							j->)-k, k->0

      Definitions: 
          x->y   Send    posted on process x; sending   to   process y
          y)-x   Receive posted on process x; expecting from process y
          y->)-x Send/Receive pair completed on process x