【问题标题】:Passing 3d arrays using MPI_Bcast使用 MPI_Bcast 传递 3d 数组
【发布时间】:2013-08-14 01:16:41
【问题描述】:

我正在尝试使用MPI_Bcast 将 3D 数组传递给所有其他进程(在 FORTRAN 77 中)。 v1 是一个普通的块数组。我也不确定是否需要将公共数组v1 的计算值广播给所有其他进程,否则它们会因为通用而在每个进程中更改。以下是相关代码:

  parameter (nprocz=48,nzro=1)

    do i=i101,i102
      dist  = 0.015*float(i-iv0)
      adamp = exp(-dist*dist)
      do j = je0, je1-1
      do k = ke0, ke1
        v1(k,j,i) = v1(k,j,i)*adamp
      end do
      end do
    end do

    nmpi01=floor((iv0-ie0-nzro)/(nprocz-1))
    if (mpirank .le. nprocz-2) then
       i101=ie0+(mpirank*nmpi01)
       i102=ie0+(mpirank+1)*nmpi01-1
    else
       i101=ie0+(mpirank*nmpi01)
       i102=iv0-1
    endif

   MPI_Bcast(v1(:,:,i101:i102),(ke1-ke0+1)*(je1-je0)*(i102-i101+1)
 & ,MPI_FLOAT,mpirank,MPI_COMM_WORLD,ierr01)

我收到错误消息:

PGFTN-S-0081-Matrix/vector v1 illegal as subprogram argument

传入的数组大小是正确的。有什么意见吗?


我更正了代码并遍历了排名并计算了每个排名中 rcount 和 displs 的所有元素:

integer :: myscount, myi101

do rank = 0, nprocz-1
  nmpi01=floor((iv0-ie0-nzro)/(nprocz-1))
  if (rank .le. nprocz-2) then
    i101=ie0+(rank*nmpi01)
    i102=ie0+(rank+1)*nmpi01-1
  else
    i101=ie0+(rank*nmpi01)
    i102=iv0-1
  endif
  scount=(i102-i101+1)*(je1-je0)*(ke1-ke0+1)
  rcount(rank+1)=scount
  displs(rank+1)=rank*scount+1
  if (rank .eq. mpirank) then
    myscount = scount
    myi101 = i101
 end if
end do

scount = myscount
i101 = myi101

call mpi_allgatherv(...)

但仍然是错误的结果。 1-在我的情况下,每个部分的结果都用于下一部分,尤其是在mpi_allgatherv之后。所以我需要在每个mpi_allgatherv之后添加mpi_barrier吗? 2-应该使用 mpi_in_place 吗?考虑我只有一个 3d 数组 v1,每个子数组 v1(1,1,i) 是由某个过程计算的,我想将计算的子数组放在同一数组的适当部分。 3-我想我应该有displs(i) = sum(rcount(1:i-1))+1 for i=>2 考虑到在 fortran77 中总是 displs(1)=1。所以我更正了这个:循环之前displs(1)=1,循环内部displs(rank+2)=rank*scount+1和循环之后displs(nprocz+1)=0。我说的对吗?

【问题讨论】:

  • 你能展示最小的完整代码示例来演示这个问题吗?请注意,我并没有说,将您的所有代码复制并粘贴到问题中,因为这对我们来说太多了,无法解析。当您提供更好的信息时,您可能会找到问题的答案。
  • wesley 我编辑了我的帖子。感谢您的任何评论
  • 如果你CALL MPI_Bcast(...)会发生什么?
  • @IRO-bot 为什么打电话?那不是子程序。我试图删除 mpi_bcast 看看会发生什么。数组 v1 是一个公共块数组,对每个进程都是全局的。但仍然不确定我是否使用每个进程计算该数组的某个部分,该部分的更改将在其他进程中进行。你怎么看
  • 是的,在 Fortran 中,所有 MPI 例程都是子例程。您使用什么 MPI 实现? MPI_FLOAT 作为一种数据类型看起来也很奇怪,请参阅 computing.llnl.gov/tutorials/mpi/#Derived_Data_Types。在您的情况下,对MPI_Bcast 的调用将从根进程mpirank 向所有其他进程发送v1 的一部分。 v1 必须在所有进程上声明。如何使用MPI_Bcast,请参阅open-mpi.org/doc/v1.7/man3/MPI_Bcast.3.php

标签: fortran mpi fortran-common-block


【解决方案1】:

我记得,Fortran 77 对数组下标的限制比 Fortran 90 更严格,而 pgftn 是 Fortran 77 编译器。我会尝试将v1(1,1,i101) 传递给mpi_bcast,而不是v1(:,:,i101:i102)。 (或者使用带有“-Mfixed”标志的 pgf95。)

如果每个进程都需要查看 v1,那么您确实需要使用 MPI 进行通信。 MPI 任务之间不共享变量,即使是公共块中的任务也不共享。但是,如果每个进程都在计算 v1 的不同部分,那么每个进程都需要其他进程的一部分,那么您不能使用 mpi_bcast 来执行此操作;请改用mpi_allgather

另外,如上所述,当您使用 MPI 程序时,您应该 call 它们,因为它们是子程序。

【讨论】:

  • @Sean patrick santos 所以我首先尝试了这个:scount=(i102-i101+1)*(je1-je0)*(ke1-ke0+1) rcount(mpirank+1)=scount displs (mpirank+1)=mpirank*scount+1 调用 MPI_ALLGATHERV(v1(1,1,i101),scount,MPI_REAL,v1(1,1,1) ,rcount,displs,MPI_REAL,MPI_COMM_WORLD,ierr004) 但我知道了错误:PMPI_Allgatherv 中的致命错误:内部 MPI 错误!,错误堆栈:... MPIR_Localcopy(378).......:memcpy 参数相互别名,dst=0x7ccddb44 src=0x7ccddb40 len=3642752
  • @ Sean patrick santos 然后我将其更改为: call MPI_ALLGATHERV(MPI_IN_PlACE,scount,MPI_REAL,v1(1,1,1) ,rcount,displs,MPI_REAL,MPI_COMM_WORLD,ierr004) 但内存是增量使用,直到程序崩溃。每种情况的问题是什么?
  • 对于第一个命令,问题只是你试图在同一个缓冲区中发送和接收;你需要MPI_IN_PLACE。对于第二个,rcountdispls 的参数必须是向量。不知道你通过了什么,我无法告诉你问题可能是什么。
  • 请看我对我的问题的回答
猜你喜欢
  • 2017-01-26
  • 2013-11-19
  • 1970-01-01
  • 2017-06-29
  • 1970-01-01
  • 1970-01-01
  • 2015-08-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多