使用MPI_Bcast传递3d数组

时间:2013-08-12 16:17:54

标签: fortran mpi fortran-common-block

我尝试使用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和displ的所有元素:

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_barrier之后添加mpi_allgatherv吗? 2 - 应该使用mpi_in_place吗?我认为我只有一个3d数组v1,每个子数组v1(1,1,i)由某个进程计算,我想把计算出的子数组放在同一个数组的相应部分。 3-我想i => 2我应该displs(i) = sum(rcount(1:i-1))+1,考虑到在fortran77中总是displs(1)= 1。所以我更正了这一点:在循环displs(1)=1之前,在循环displs(rank+2)=rank*scount+1内和循环displs(nprocz+1)=0之后。我是对的吗?

1 个答案:

答案 0 :(得分:0)

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

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

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