MPI_SENDRECV是如何工作的?

MPI_SENDRECV是如何工作的?,mpi,Mpi,我有一个关于MPI_SENDRECV的问题。 以下是一个例子: 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_C

我有一个关于MPI_SENDRECV的问题。 以下是一个例子:

 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
在这之后,我们得到了34和34。 我的问题是我们要替换MPI_SENDRECV(如果我们假设MPI_SENDRECV先发送,然后接收)

那么这就是僵局
这意味着MPI_SENDRECV不是先发送然后接收,而是同时发送ans接收,对吗?

你说得对,
MPI_SENDRECV
与先发送后接收不同。可以将其视为一个
MPI-Isend
MPI-Irecv
,以及一对
MPI-Wait
s。因此,实际上,发送和接收是并行进行的

顺便说一句,这就是它在MPI库中通常的实现方式

如果您想修复第二个示例中的死锁,那么进程必须以不同的顺序发出发送和接收。因此,秩0将发出一个发送,然后是接收,秩1-一个接收,然后是发送

即使消息被路由到接收进程B,进程B仍然必须确认它想要接收A的数据。一旦这样做,数据就被传输了。过程A确认数据已传输,并可能恢复工作

因此,您的第二个代码不能满足条件,这似乎是因为您没有应答其他人的呼叫。应该是这样的:

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

非常感谢,我现在知道了!MPI_Sendrecv_replace()如何工作?它是否使用阻塞发送和接收?MPI_Sendrecv_replace可能需要一个单独的问题(这是一个新添加的操作)。我可以想象有两种不同的实现(我相信致力于优化MPI的研究小组会将这些实现相互比较)。OpenMPI使用的实现将要发送的数据复制到临时缓冲区中,然后调用常规的Sendrecv()
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