Concurrency 并行MPI程序/重新定义MPI通信世界

Concurrency 并行MPI程序/重新定义MPI通信世界,concurrency,fortran,mpi,Concurrency,Fortran,Mpi,我有一个用MPI并行的Fortran程序。对于我知道的某个应用程序,我希望公平地运行该程序的2个实例,但不是完全相同的实例。这两个并发运行的程序必须在运行时相互通信 我认为最简单的方法之一是定义一个全局通信器,例如跨所有流程的MPI_COMM_WORLD_global。然后,我将继续重新定义通用的全局通信器MPI_COMM_WORLD,将其定义为该程序实例使用的进程总数。注意,尽管我提到了该程序的多个实例,但在这种情况下,只有一个实际程序在运行 我希望将MPI_COMM_WORLD保持为程序“t

我有一个用MPI并行的Fortran程序。对于我知道的某个应用程序,我希望公平地运行该程序的2个实例,但不是完全相同的实例。这两个并发运行的程序必须在运行时相互通信

我认为最简单的方法之一是定义一个全局通信器,例如跨所有流程的MPI_COMM_WORLD_global。然后,我将继续重新定义通用的全局通信器MPI_COMM_WORLD,将其定义为该程序实例使用的进程总数。注意,尽管我提到了该程序的多个实例,但在这种情况下,只有一个实际程序在运行

我希望将MPI_COMM_WORLD保持为程序“this”实例使用的进程总数,以避免在我的代码中更改通信器

因此,我的问题是,是否有一种简单的方法可以用Fortran重新定义MPI_COMM_WORLD?或者我提出的方法是错误的做法,我应该研究其他方法

提前感谢。

MPI\u COMM\u WORLD可以是常量或宏。试图重新定义它是自找麻烦

在我的OpenMPI中,它是一个值为9的参数

您必须使用模块mpi或mpif.h中的名称创建自己的变量,例如,通过使用一些自定义模块或include文件


使用一些现代文本编辑器或IDE在代码中将MPI_COMM_WORLD更改为自定义通信器应该没有那么困难。

听起来您可能在思考问题,或者只是用错误的方式描述了问题。如果两次运行调用mpiexec/mpirun的应用程序的两个独立实例,那么如果不执行一些额外的工作MPI\u COMM\u CONNECT/MPI\u COMM\u ACCEPT,两个应用程序将无法相互通信。事实上,如果您将使用同一个启动器运行应用程序的两个实例,调用mpiexec/mpirun一次,那么您应该在代码开头调用类似MPI\u COMM\u SPLIT的命令,将通信器一分为二。这将为应用程序的每一半提供一个不同的通信器,您可以在应用程序通信的一半时间内将该通信器用于本地,并在需要进行全局通信时使用MPI_COMM_WORLD


这就是MPI的全部理念。您应该使用不同的通讯器在应用程序中创建不同的通讯空间。不应该在MPI_COMM_WORLD上执行所有操作。

您可以使用MPI_COMM_spawn将MPI应用程序的一个副本复制到另一个副本上。执行此操作时,每个应用程序中的MPI_COMM_WORLD将仅包含该特定应用程序中的进程,即将有两个单独的MPI_COMM_WORLD—一个用于父作业,另一个用于子作业。然后,两份副本将能够通过已建立的内部通讯器进行通讯。父作业在MPI_COMM_SPAWN的输出参数中接收intercommunicator,而子作业可以通过调用MPI_COMM_GET_parent来获取它

内部通讯器与常规内部通讯器(如MPI_COMM_WORLD)有所不同。它们是不对称的,因为它们中有本地和远程进程组,本地操作是不可能的。可以使用MPI_Intercom_MERGE将内部通讯器转换为内部通讯器

在您的案例中,相关逻辑是:

第一份

第二个衍生副本

这段代码有点不对称,因为有一个父级生成另一个副本,并且在两个程序中都需要一点不同的逻辑。您仍然可以在父级中调用MPI_COMM_GET_PARENT,它只会返回MPI_COMM_NULL。这样,您的程序将知道它是第一个副本并进行繁殖


您也可以将SupercMM命名为MPI_COMM_WORLD_GLOBAL,但您应该注意到,MPI_name前缀是为MPI调用和常量保留的,您不应该将其用于自己的变量。

我当然也可以使用稍微不同的名称定义本地MPI_COMM_WORLD,并在整个程序中使用它们。然而,这需要替换代码中的许多行。但我理解你对重新定义MPI通信世界的担忧。。。我会尽量避免的。你对表演这样的阴影有什么建议吗?每当我尝试这样做时,编译器都会告诉我MPI_COMM_WORLD已经在mpif.hYes中定义了,那么您就不能使用MPI.f了。或者至少不是直接的。这就是为什么我建议使用不同的通信器。只要使用一个好的编辑器或sed或任何自动搜索和替换工具。我可能一开始就不清楚我的问题,对不起。在理想情况下,我希望使用MPI_COMM_SPLIT将我的全局通信器分成2个,并将生成的子通信器命名为MPI_COMM_WORLD,如下所示
这样可以避免我在团队中编写代码时需要更改代码的所有内容,所以在任何地方更改代码都不太理想。所以我想称我的全球通讯员为MPI_COMM_WORLD_global和子通讯员MPI_COMM_WORLD。但这样做似乎不是小事。啊,这更有意义。那么你问题的答案是,不要那样做。不幸的是,没有很好的方法来重命名MPI_COMM_WORLD。你的其他沟通者相对容易做到,但这一点是不可能的。
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)