使用4个线程的MPI_SENDRECV时出现问题

问题描述 投票:1回答:1

作为一个小问题,我试图在4个处理器之间发送一个整数:0 - > 3(秩0发送到和从3等级接收),2 - > 1,1 - > 2,3 - > 0.它从不完成执行并挂起,可能正在等待其他线程的响应。

我正在使用mpif90 ...编译代码并使用mpiexec -np 4 ...运行。以下是最小代码段:

program sendrecv
  implicit none
  include "mpif.h"
  integer :: foo, bar
  integer :: mpi_rank, mpi_size, ierr
  integer :: mpi_sendto, mpi_recvfrom
  integer :: istat(MPI_STATUS_SIZE), status, i

  call MPI_INIT(ierr)
  call MPI_COMM_SIZE(MPI_COMM_WORLD, mpi_size, ierr)
  call MPI_COMM_RANK(MPI_COMM_WORLD, mpi_rank, ierr)
  print *, "SENDING..."

  if (mpi_rank .eq. 0) then
    mpi_sendto = 3; mpi_recvfrom = 3
  else if (mpi_rank .eq. 1) then
    mpi_sendto = 2; mpi_recvfrom = 2
  else if (mpi_rank .eq. 2) then
    mpi_sendto = 1; mpi_recvfrom = 1
  else
    mpi_sendto = 0; mpi_recvfrom = 0
  end if

  foo = mpi_rank
  do i = 1, 5
    foo = mpi_rank
    call MPI_SENDRECV(foo, 1,&
                    & MPI_INTEGER, mpi_sendto, mpi_rank * 10 + i,&
                    & bar, 1,&
                    & MPI_INTEGER, mpi_recvfrom, mpi_rank * 10 + i,&
                    & MPI_COMM_WORLD, istat, ierr)
  end do

  print *, "...DONE"
  call MPI_FINALIZE(ierr)
end

我真的不明白为什么这个程序会挂起,也许我错过了什么或做了一些非常错误的事情。如果我理解正确,MPI_SENDRECV只是非阻塞sendrecv与两个wait-s。在那种情况下,比方说,如果rank=0发送给rank=3它不应该有任何问题,对吧?

我尝试从不同的线程发送/接收,即这样做:

  if (mpi_rank .eq. 0) then
    mpi_sendto = 1; mpi_recvfrom = 3
  else if (mpi_rank .eq. 1) then
    mpi_sendto = 2; mpi_recvfrom = 0
  else if (mpi_rank .eq. 2) then
    mpi_sendto = 3; mpi_recvfrom = 1
  else
    mpi_sendto = 0; mpi_recvfrom = 2
  end if

还是行不通。

UPD正如指出的那样,在执行SENDRECV时标签应该是相同的,但是如果在循环中进行此调用,类似的标签没有多大帮助(参见修改后的代码)。旧版:

call MPI_SENDRECV(foo, 1,&
                    & MPI_INTEGER, mpi_sendto, 200,&
                    & bar, 1,&
                    & MPI_INTEGER, mpi_recvfrom, 100,&
                    & MPI_COMM_WORLD, status, ierr)

UPD#2实际上,如果有人感兴趣的话,我发现了一个discussion确切地说我为什么SENDRECV-s有时可能会死锁的问题。

parallel-processing fortran mpi
1个回答
2
投票

术语“线程”在这里有误导性,你应该谈论MPI任务或MPI过程(两者都是等价的)。

根本原因是标签不匹配。您发送标签200但收到标签100

此外,你应该使用istat而不是status作为MPI_Sendrecv()的状态参数。

以下是修复程序的方法

call MPI_SENDRECV(foo, 1,&
                & MPI_INTEGER, mpi_sendto, 200,&
                & bar, 1,&
                & MPI_INTEGER, mpi_recvfrom, 200,&
                & MPI_COMM_WORLD, istat, ierr)
© www.soinside.com 2019 - 2024. All rights reserved.