1

我有一个代码可以计算一些导体中的热传递。一个导体中发生的事情不会影响模型中的其他导体。所以我试图让这些导体的解决方案并行运行,每个处理器采用一组不同的导体。现在,我认为代码可以在一个核心上运行,直到它进入我放置命令的循环:

MPI_INIT

然后在我请求的许多内核上运行这部分代码,然后在命令之后返回在一个内核上运行:

MPI_FINALIZE

遇到。但我看到的是输入文件被两个核心读取(如果我使用 2 个核心),并且所有输出也被打印两次。MPI 不像我想的那样工作吗?如果没有,那么我怎样才能实现我想要的行为?我只希望该代码段的代码在多个内核上运行,而不是在 MPI_INIT 和 MPI_FINALIZE 之外的任何其他子例程或部分代码中运行。

4

2 回答 2

9

这是一个常见的误解,尤其是在有过 OpenMP 之类的经验的人中,线程在程序的不同点被分叉和连接。

在 MPI 中,MPI_Init初始化MPI_Finalize并完成你的 MPI 库;就是这样。尽管该标准故意对 Init 之前和 Finalize 之后发生的事情保持沉默,但实际上,您mpirun或您的mpiexec命令通常会创建和启动进程。如果你输入

mpirun -np 4 hostname

例如,启动了四个进程,每个进程都运行hostname命令——这绝对不是 MPI 可执行文件,并且其中没有任何MPI_InitMPI_Finalize调用。这些进程中的每一个都运行可执行文件,从头到尾,所以你得到四个输出。启动进程的是 mpirun(或 mpiexec),而不是程序内部的任何 MPI 函数调用。

然后,在您的程序中,整个程序将由您请求的多个进程运行。

于 2012-06-19T19:52:57.967 回答
3

我不认为我完全理解这个问题,但首先要注意的是 MPI 最多可以初始化一次。如此反复做

MPI_Init
...
MPI_Finalize

不允许。此外,MPI_InitMPI_Finalize是昂贵的操作;您不想循环调用它们。

MPI 最初是围绕静态流程模型设计的,这意味着一组流程启动、完成工作并退出。听起来您希望在运行时更改进程数。这在 MPI-2 中是可能的(参见 参考资料MPI_Comm_spawn)。

另一方面,不断启动和关闭进程会很慢。仅仅因为一个进程已经调用MPI_Init并不意味着它必须参与所有的通信。这是我解决问题的方法:

  1. 启动进程池。在程序开始时调用MPI_Init所有进程,即使是那些只能在本地工作的进程。
  2. 在每个循环迭代中,为需要使用 进行通信的进程创建一个新的通信器MPI_Comm_create,并将其用于所有通信而不是MPI_COMM_WORLD.
  3. 在程序结束时,所有进程调用MPI_Finalize.
于 2012-06-19T19:50:04.120 回答