8

我有一个关于 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

在此之后我们得到 3 4 和 3 4。我的问题是我们替换 MPI_SENDRECV(如果我们假设 MPI_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,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

那么这将是死锁所以这意味着 MPI_SENDRECV 它不是先发送然后接收,而是同时发送和接收,对吗?

4

2 回答 2

19

你是对MPI_Sendrecv的,发送后接收不一样。把它想象成一个MPI_Isend,MPI_Irecv和一对MPI_Waits。所以实际上,发送和接收是并行进行的。

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

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

于 2012-06-13T17:28:22.410 回答
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
于 2015-05-15T15:47:52.700 回答