使用 C++ 和 MPI 进行并行编程 -- 相同的可执行文件可能吗?



我想创建一个可以在运行时同时使用 MPI 和不使用 MPI 的程序,我已经到了我认为这是不可能的地步。

例如,MPI 程序可能如下所示:

#include <mpi.h>
int main(int argc, char* argv[])
{
MPI_Init(&argc, &argv);
...
MPI_Finalize ();
return 0;
}

但是为了允许没有安装 MPI 的用户编译它,我必须将其包装在#if的周围:

// Somewhere here, pull in a .h file which would set HAVE_MPI to 0 or 1
#if HAVE_MPI
#include <mpi.h>
#endif
int main(int argc, char* argv[])
{
#if HAVE_MPI
MPI_Init(&argc, &argv);
#endif
...
#if HAVE_MPI
MPI_Finalize ();
#endif
return 0;
}

直到现在,我认为我是对的? 如果这个程序编译成a.outHAVE_MPI设置为1,它将运行为:mpirun -np 4 ./a.outmpirun -np 1 ./a.out。 它永远不能像./a.out那样运行,因为即使它不在mpirun内运行,它也会调用MPI_*函数。

我想实现我想要的 - 一个可以在有和没有mpirun的情况下运行的可执行文件是不可能的。 唯一的选择是创建两个单独的可执行文件 - 一个HAVE_MPI设置为 0,另一个设置为 1。 这是正确的还是我错过了一些关于如何使用 MPI C++程序实现的内容?

作为旁注,我认为共享内存并行化(即 OpenMP)并非如此。 同一个可执行文件应该适用于单个或多个线程。

我的理解正确吗?

编译的 MPI 程序除了mpirun调用之外,还需要运行时的 MPI 库(并非所有 MPI 实现都需要 1 个进程,也不是在所有情况下都需要)。因此,要在某些情况下仅在运行时运行 MPI 函数而不依赖于 MPI,需要动态加载使用 MPI 的代码。这可以通过将 MPI 相关函数放在共享库组件中并在运行时根据您的需求加载它们来完成。

OpenMP也是如此:OpenMP 代码需要 OpenMP 编译器标志,例如-fopenmp创建运行时所需的 OpenMP 实现的依赖项。话虽如此,通用GOMP(GCC)运行时或IOMP运行时(ICC/Clang)通常默认安装在大多数Linux计算机上(尤其是前者,因为GCC通常是默认编译器并与GOMP捆绑在一起)。

使用共享库可帮助您在两个并行实现之间轻松切换:MPI 和 OpenMP。话虽如此,这意味着初始化、完成和通信集合必须包装在独立于程序编译的外部库中。库函数可以在启动时动态加载,也可以在运行时使用dlopen手动加载(请参阅此相关文章)。

正如注释中指出的,使用预处理器指令是在编译时解析的,这就是为什么在使用它们需要重建程序两次的原因。共享库不需要这样做(尽管要在运行时执行的所有发散部分都需要单独编译)。

最新更新