【问题标题】:MPI_Allgather receiving junkMPI_Allgather 接收垃圾
【发布时间】:2019-05-30 12:08:32
【问题描述】:

我有以下代码:

              real          :: s_s, d_s, s_r(size), d_r(size)
              integer       :: k, k_r(size)

              ! - size = number of processors
              ! - Do something to initialise s_s, d_s, k
              write(*,*) "SENDING >>>>"
              write(*,*) s_s, d_s
              call MPI_Allgather( s_s, 1, MPI_REAL,
 &                 s_r, 1, MPI_REAL, MPI_COMM_PGM, mpi_err)

              call MPI_Allgather( d_s, 1, MPI_REAL,
 &                 d_r, 1, MPI_REAL, MPI_COMM_PGM, mpi_err)

              call MPI_Allgather ( k, 1, MPI_INTEGER,
 &                 k_r, 1, MPI_INTEGER, MPI_COMM_PGM, mpi_err)


              write(*,*) "RECEIVED <<<<"
              write(*,*) s_r, d_r, kr

这会生成以下输出:

SENDING >>>>
  -1803.80339864908       0.616157856320407     
 RECEIVED <<<<
  6.953077622513053E-310  3.565412685916647E-314  1.221334434576037E-314
  1.498827614035474E-314  6.952991536467244E-310  6.953288052096687E-310
  6.953108563966064E-310  2.350861403096908E-314           4           1
           2           3

kr 被正确收集,但是 s_r 和 d_r 似乎正在接收垃圾。这可能是因为 MPI 数据类型吗?我尝试使用 MPI_REAL MPI_REAL8MPI_DOUBLE 但这没有用。此外,mpi_err = MPI_SUCCESS

我能做些什么来解决这个问题?

编辑 1 我参与了以下原型程序:

program allgather
  implicit none

  include "mpif.h"

  real a(4)
  integer rank,size,ierr
  real as(4)
  real ar(16)
  integer i, j, k,z 

  a=1
  call MPI_INIT(ierr)
  call MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierr)
  call MPI_COMM_SIZE(MPI_COMM_WORLD, size, ierr)
  if(size.ne.4)then 
     write(*,*)'Error!:# of processors must be equal to 4'
     write(*,*)'Programm aborting....'
     call MPI_ABORT(ierr)
  endif

  do k=1,4
     if ( rank == (mod(k, size))) then
        a(k)  = k
     else
        a(k)  = 0.0 
     endif
  enddo

  write(*,*) "Rank :", rank
  write(*,*) a

  call MPI_Allgather(a, 4, MPI_REAL, ar,
 &     4,
 &     MPI_REAL, MPI_COMM_WORLD, ierr)

  write(*,*) "Recieved array"
  write(*,*) ar

  do i = 1, 16
     if ( ar(i) /= 0.0 ) then
        z = mod(i, size)
        if ( z == 0 ) then
           a( size ) = ar(i)
        else
           a ( z ) = ar(i)
        endif
     endif
  enddo

  write(*,*) "---------"
  write(*,*) a
  write(*,*) "---------"

  call MPI_FINALIZE(ierr)
  end

这会产生预期的结果,即ar 不会收集垃圾。但是,我无法区分实现之间的区别。

【问题讨论】:

  • 我现在看不出你的第一个块有什么问题。您能否在重现您的问题时最小限度地更改 that 版本(通过为要传递的值设置一些初始值)以使其可运行?如果你不能,很可能是你从你的真实代码中删除了一些导致错误的东西。
  • 一个不同的是通信器,我看到通信器MPI_COMM_PGM 已在另一个模块中定义。我使用该模块并在代码中指定通信器。重现错误的最小示例将非常冗长,因为这段代码深深嵌入类型绑定方法中。由于它发送的是正确的值,我认为只有接收存在问题。
  • 在这种情况下,您要求我们调试我们看不到的代码。
  • @AndrasDeak,明白了!将很快上传一个最小的代码
  • @AndrasDeak 实际上,问题似乎出在控制缓冲区大小的代码的另一部分。目前,我已经解决了这个问题(见答案)。

标签: fortran mpi openmpi


【解决方案1】:

事实证明,对于该项目,要使用的数据类型是MPI_FLT。奇怪的是 MPI_FLT 有效,而不是 MPI_REALx 其中 x=4,8 也不是 MPI_FLOAT。我在项目中 grep-ed MPI_FLT 以查看它的定义,但在项目中的任何地方都没有出现。

我使用的 OpenMPI 版本是:

$ mpirun --version
mpirun (Open MPI) 3.0.0

我使用的编译器是:

$ mpifort --version
ifort (IFORT) 19.0.1.144 20181018

在以后的编辑中,我将详细说明原因。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-21
    • 2018-12-30
    • 1970-01-01
    • 1970-01-01
    • 2011-12-21
    相关资源
    最近更新 更多