How does the MPI_SENDRECV work?

mpi
16,480

Solution 1

You are right, MPI_Sendrecv is not the same a send followed by a receive. Think of it as an MPI_Isend, MPI_Irecv, and a pair of MPI_Waits. So in effect, the send and receive proceed in parallel.

Incidentally, this is how it is commonly implemented in the MPI libraries.

If you wanted to fix the deadlock in your second example, the processes would have to issue the sends and receives in a different order. So rank 0 would issue a send followed by receive, and rank 1 - a receive followed by a send.

Solution 2

Even though the message is routed to receive process B , process B still has to acknowledge that it wants to receive A's data. Once it does this, the data has been transmitted. Process A is acknowledged that the data has been transmitted and may go back to work.

So your second code can't satisfy the condition, which seems like that you don't answer the call by others. It should be like the follows:

if (myrank == 0) then
   call MPI_SEND(b,1,MPI_REAL,1,0,MPI_COMM_WORLD,ierr)
   call MPI_RECV(a,1,MPI_REAL,1,0,MPI_COMM_WORLD,istat,ierr)
elseif (myrank == 1) then
   call MPI_SEND(b,1,MPI_REAL,0,0,MPI_COMM_WORLD,ierr)
   call MPI_RECV(a,1,MPI_REAL,0,0,MPI_COMM_WORLD,istat,ierr)
end if
Share:
16,480
Dong Siwei
Author by

Dong Siwei

Updated on July 29, 2022

Comments

  • Dong Siwei
    Dong Siwei over 1 year

    I have a question about MPI_SENDRECV. here is an example:

     PROGRAM sendrecv
      IMPLICIT NONE
      INCLUDE "mpif.h"
      INTEGER a,b,myrank,nprocs,ierr
      integer istat(MPI_STATUS_SIZE)
      CALL MPI_INIT(ierr)
      CALL MPI_COMM_SIZE(MPI_COMM_WORLD, nprocs, ierr)
      CALL MPI_COMM_RANK(MPI_COMM_WORLD, myrank, ierr)
      if (myrank.eq.0) then
         a=1;b=3
      else
         a=2;b=4
      endif
    
      if (myrank == 0) then
         call MPI_SENDRECV(b,1,MPI_REAL,1,0,
     .                     a,1,MPI_REAL,1,0,
     .                     MPI_COMM_WORLD,istat,ierr)
      elseif (myrank == 1) then
         call MPI_SENDRECV(b,1,MPI_REAL,0,0,
     .                     a,1,MPI_REAL,0,0,
     .                     MPI_COMM_WORLD,istat,ierr)
      end if
      if (myrank.eq.0) then
         write(*,*) b,a
      else
         write(*,*) a,b
      endif
      CALL MPI_FINALIZE(ierr)
      END
    

    After this we get 3 4 and 3 4. My question is that is we replace the MPI_SENDRECV(if we assume that MPI_SENDRECV is send first and then receive)

    if (myrank == 0) then
       call MPI_SEND(b,1,MPI_REAL,1,0,MPI_COMM_WORLD,ierr)
       call MPI_RECV(a,1,MPI_REAL,0,0,MPI_COMM_WORLD,istat,ierr)                  
    elseif (myrank == 1) then
       call MPI_SEND(b,1,MPI_REAL,0,0,MPI_COMM_WORLD,ierr)
       call MPI_RECV(a,1,MPI_REAL,1,0,MPI_COMM_WORLD,istat,ierr)                      
    end if
    

    Then this will be deadlock So this means that MPI_SENDRECV it not first sends and then receives, but sends ans receives simultaneously,right?