MPI中的多个通信器

5
这个问题的背景在于一些计算领域,比如计算流体力学(CFD)。在某些关键区域,我们经常需要更细的网格,而背景网格可以更粗。例如,在气象学中跟踪冲击波和嵌套域的自适应细化网格。使用笛卡尔拓扑结构,并且将域分解如下图所示。在这种情况下,使用4*2=8个处理器。单个数字表示处理器的等级,(x,y)表示其拓扑坐标。 Fig 1. Basic topology 假设在等级为2、3、4、5(中间位置)的区域中细化了网格,并且在本例中定义了局部细化比率R=D_coarse/D_fine=2。由于网格被细化,因此时间推进也应该被细化。这需要在细化区域计算时间步长t、t+1/2*dt、t+dt,而在全局区域只计算时间步长t和t+dt。这需要一个更小的通信器,其中仅包括中间等级的排名进行额外计算。以下是全局等级+坐标和相应的本地等级(红色)示意图: Local refinement and their ranks and topological coordinate 然而,我在实现这个方案时遇到了一些错误,并且Fortran的代码片段(不完整)如下:
integer :: global_comm, local_comm   ! global and local communicators
integer :: global_rank, local_rank   !
integer :: global_grp,  local_grp    ! global and local groups
integer :: ranks(4)                  ! ranks in the refined region
integer :: dim                       ! dimension
integer :: left(-2:2), right(-2:2)   ! ranks of neighbouring processors in 2 directions
ranks=[2,3,4,5]

!---- Make global communicator and their topological relationship
call mpi_init(ierr)
call mpi_cart_create(MPI_COMM_WORLD, 2, [4,2], [.false., .false.], .true., global_comm, ierr)
call mpi_comm_rank(global_comm, global_rank, ierr)
do dim=1, 2
    call mpi_cart_shift(global_comm, dim-1, 1, left(-dim), right(dim), ierr)
end do


!---- make local communicator and its topological relationship
! Here I use group and create communicator

! create global group
call mpi_comm_group(MPI_COMM_WORLD, global_grp, ierr)

! extract 4 ranks from global group to make a local group
call mpi_group_incl(global_grp, 4, ranks, local_grp, ierr)

! make new communicator based on local group
call mpi_comm_create(MPI_COMM_WORLD, local_grp, local_comm, ierr)

! make topology for local communicator
call mpi_cart_create(global_comm, 2, [2,2], [.false., .false.], .true., local_comm, ierr)

! **** get rank for local communicator
call mpi_comm_rank(local_comm, local_rank, ierr)

! Do the same thing to make topological relationship as before in local communicator.
 ...

当我运行程序时,问题出在“****获取本地通信器等级”步骤。我的想法是建立两个通信器:全局通信器和本地通信器,本地通信器嵌入在全局通信器中。然后在全局和本地通信器中分别创建它们的对应拓扑关系。我不知道我的概念是否正确或语法是否有误。如果您能给我一些建议,非常感谢。
错误信息为:
*** An error occurred in MPI_Comm_rank
 *** reported by process [817692673,4]
 *** on communicator MPI_COMM_WORLD
 *** MPI_ERR_COMM: invalid communicator
 *** MPI_ERRORS_ARE_FATAL (processes in this communicator will now abort,
 ***    and potentially your MPI job)

你可以通过 ierr 获取操作的状态,你尝试过在每个操作和每个进程中检查它们以验证到目前为止所有操作是否确实正常工作了吗? - d_1999
我之前一直使用粗略的背景网格设置(只有一个全局通信器),这没有问题。当我测试两个通信器的情况时,如果我注释掉所有来自! ****步骤(本地通信器的mpi_comm_rank)的内容,则程序可以正常工作,并显示如上所示的错误消息。我还添加了一个命令来测试调用mpi_comm_rank步骤后ierr是否等于0,但是这个命令没有被执行,并且程序在调用mpi_comm_rank步骤时中止并出现错误。 - Yongxin
你为什么要两次创建 local_comm?(例如,首先使用 mpi_comm_create(),然后使用 mpi_cart_create() - Gilles Gouaillardet
@GillesGouaillardet mpi_comm_create() 用于创建仅有4个rank的小型communicator。中间区域应该进行一些独立的计算,因此它需要与相邻处理器通信,并且mpi_cart_create()在本地通信中构建了一个Cartesian拓扑结构。 - Yongxin
@GillesGouaillardet,我找到问题所在了。我创建了两个local_comm。在mpi_cart_create()步骤中,我应该使用local_comm作为旧通信器来创建一个新的笛卡尔通信器。谢谢。 - Yongxin
1个回答

2
您正在从全局通信器的组创建一个2x2笛卡尔拓扑结构,其中包含八个排名。因此,在其中四个排名中,由MPI_Cart_create返回的local_comm值将为MPI_COMM_NULL。在空通信器上调用MPI_Comm_rank会导致错误。如果我正确理解您的逻辑,您应该改为执行以下操作:
if (local_comm /= MPI_COMM_NULL) then
  ! make topology for local communicator
  call mpi_cart_create(local_comm, 2, [2,2], [.false., .false.], .true., &
                     local_cart_comm, ierr)

  ! **** get rank for local communicator
  call mpi_comm_rank(local_cart_comm, local_rank, ierr)

  ...
end if

谢谢。实际上,这一步将本地组的本地通信器设置为4个MPI_COMM_NULL值,用于local_comm。如果我直接执行以下操作:`! 为本地通信器创建拓扑 call mpi_cart_create(local_comm, 2, [2,2], [.false., .false.], .true., & local_cart_comm, ierr)`这是无法执行的。因此,在mpi_cart_create()之前,我使用了一个if (local_comm /= mpi_comm_null)条件来创建local_cart_comm - Yongxin
当然,我犯了我在第一段描述的同样的错误 :) - Hristo Iliev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接