我有一个使用MPI并行化的Fortran程序。对于某个应用程序,我知道要运行此程序的2个相当(但不是绝对)相同的实例。这两个并发运行的程序必须在运行时相互通信。
我认为最简单的方法之一就是定义一个跨越所有进程的全局通信器(例如MPI_COMM_WORLD_GLOBAL)。然后我将继续将通常的全局通信器MPI_COMM_WORLD重新定义为此程序实例使用的进程总量(请注意,虽然我谈到该程序的多个实例,但在这种情况下只会运行1个实际程序)。
我希望将MPI_COMM_WORLD保留为用于“此”程序实例的进程总量,以避免在整个代码中更改通信器。
因此,我的问题是,有没有直接的方法在Fortran中重新定义MPI_COMM_WORLD?或者我提议的做法是不好的做法,我应该研究其他方法。
提前致谢。
答案 0 :(得分:3)
MPI_COMM_WORLD
可以只是常量或宏。试图重新定义它是在寻找麻烦。
在我的OpenMPI中,它是parameter
,值为9。
您必须使用该名称创建自己的变量,该变量会影响模块mpi
或mpif.h
中的变量,例如,使用某个自定义模块或包含文件。
使用一些现代文本编辑器或IDE将MPI_COMM_WORLD
更改为代码中的自定义通信器应该不难。
答案 1 :(得分:3)
听起来你可能会以错误的方式思考事物(或者只是描述它们)。如果您运行应用程序的两个单独实例(两次调用mpiexec
/ mpirun
),那么两个应用程序将无法在不做额外工作的情况下相互通信(MPI_COMM_CONNECT
/ MPI_COMM_ACCEPT
)。实际上,如果您使用相同的启动器运行应用程序的两个实例(一次调用mpiexec
/ mpirun
),那么您应该在代码的开头将通信器分成两半。调用MPI_COMM_SPLIT
之类的东西。这将为您的应用程序的每一半提供不同的通信器,您只需将该通信器用于本地(在应用程序的一半内)通信,并在需要进行全局通信时使用MPI_COMM_WORLD
。
这首先是MPI的全部概念。您应该使用不同的通信器在应用程序中创建不同的通信空间。不应该在MPI_COMM_WORLD
上完成所有事情。
答案 2 :(得分:3)
您可以做的是使用MPI_COMM_SPAWN
生成另一个MPI应用程序副本。这样做时,每个应用程序中的MPI_COMM_WORLD
将仅包含该特定应用程序中的进程,即将有两个单独的MPI_COMM_WORLD
- 一个用于父作业,一个用于子作业。然后,这两个副本将能够通过已建立的互通机进行通信。父作业在MPI_COMM_SPAWN
的输出参数中接收intercommunicator,而子作业可以通过调用MPI_COMM_GET_PARENT
来获取它。
交流中心与常规的内部通信者(例如MPI_COMM_WORLD
)有所不同。它们是不对称的,因为它们中存在本地和远程进程组,并且本地操作是不可能的。可以使用MPI_INTERCOMM_MERGE
将内部通信器转换为内部通信器。
您案例中的相关逻辑将是:
首次复制
INTEGER, PARAMETER :: nprocs = 32
INTEGER :: child_intercomm, supercomm, ierr
INTEGER, DIMENSION(nprocs) :: error_codes
CHARACTER(LEN=40) :: command
! Spawn the second copy with nprocs MPI processes
command = './program2'
CALL MPI_COMM_SPAWN(command, MPI_ARGV_NULL, nprocs, MPI_INFO_NULL, 0, &
child_intercomm, error_codes, ierr)
CALL MPI_INTERCOMM_MERGE(child_intercomm, .FALSE., supercomm, ierr)
第二次(衍生)副本
INTEGER :: parent_intercomm, supercomm, ierr
CALL MPI_COMM_GET_PARENT(parent_intercomm, ierr)
CALL MPI_INTERCOMM_MERGE(parent_intercomm, .TRUE., supercomm, ierr)
代码有点不对称,因为有一个父产生另一个副本,并且在两个程序中都需要一些不同的逻辑。您仍然可以在父级中呼叫MPI_COMM_GET_PARENT
,它只会返回MPI_COMM_NULL
。这样你的程序就会知道它是第一个副本并且产生了spawn。
您也可以命名supercomm
MPI_COMM_WORLD_GLOBAL
,但是您应该注意到MPI_
名称前缀是为MPI调用和常量保留的,您不应该将它用于您自己的变量。