为什么这个MPI_SENDRECV是死锁?

时间:2012-06-13 12:51:34

标签: fortran mpi

这是我的第一篇文章。提前感谢您的帮助。这是一个非常短的测试MPI_SENDRECV的代码,我不明白。但任何人都告诉我为什么会陷入僵局?

 PROGRAM sendrecv
  INCLUDE "mpif.h"
  INTEGER ibuf(20)
  CALL MPI_INIT(ierr)
  CALL MPI_COMM_SIZE(MPI_COMM_WORLD, nprocs, ierr)
  CALL MPI_COMM_RANK(MPI_COMM_WORLD, myrank, ierr)
  a=1
  b=2
  if (myid == 0) then
     call mpi_sendrecv(a,1,mpi_real,1,0,
 .                     b,1,mpi_real,1,0,
 .                     MPI_COMM_WORLD, status,ierr)
  elseif (myid == 1) then
     call mpi_sendrecv(b,1,mpi_real,0,0,
 .                     a,1,mpi_real,0,0,
 .                     MPI_COMM_WORLD,status,ierr)
  end if
  if (myid.eq.0) then
     write(*,*) a
  endif
  if (myid.eq.1) then
     write(*,*) b
  endif
  CALL MPI_FINALIZE(ierr)
  END

1 个答案:

答案 0 :(得分:0)

正如@SteveBlackwell指出的那样,您使用myid代替myrank。如果您使用:

CALL MPI_COMM_RANK(MPI_COMM_WORLD, myid, ierr) 
相反,那么你将在那里。这里出现死锁,因为两个处理器(可能)都有myid = 0(注意,这种行为依赖于编译器 - 其他编译器可能会将它设置为某个奇怪的数字,并且您的程序似乎可以工作,但不会传递任何消息)

你的第二个问题是status被隐式声明为实变量,但MPI期望一个大小为MPI_STATUS_SIZE的整数数组。这可能有各种各样的影响 - 你可能会得到一个段错误,或者更糟糕的是,一些奇怪的内存错误,因为MPI正在写入一个它本不应该的缓冲区。 (或者,你可以使用MPI_STATUS_IGNORE,因为你还没有对状态做任何事情。)

正如@HighPerformanceMark所指出的,最佳做法是在程序中明确键入所有内容并使用IMPLICIT NONE来避免这些类型的问题。换句话说,如果您的子例程/模块/函数/主程序在声明中没有IMPLICIT NONE,那么您应该有一个非常好的理由。