我正在使用gcc
和OpenMPI。通常我使用mpirun
包装器运行MPI程序 - 例如,
mpirun -np 4 myprogram
启动4个流程。
但是,我想知道是否可以轻松生成一个自动生成的二进制文件(可能还有一些硬编码选项,如上面的-np 4
)。
我知道我可以编写一个调用程序的C包装器,如下所示:
#include <stdlib.h>
#include <unistd.h>
int main() {
char *options[] = { "mpirun", "-np", "4", "myprogram" };
execvp("mpirun", options);
/* Ignoring return value to keep example simple */
return EXIT_SUCCESS;
}
但这看起来有点笨拙,我最终得到了两个可执行文件而不是一个。
我试图明确链接MPI库,比如
gcc -o myprogram -I/usr/lib/openmpi/include/ \
-lmpi -L/usr/lib/openmpi/lib/ myprogram.c
但是当我运行生成的可执行文件时,MPI_Comm_size
将组作为组大小设置为零(就好像我已将-np 0
作为参数)。我可以使用环境变量或其他东西来传递组大小吗?或者,是否有另一种方法来构建单可执行MPI程序(使用Linux和gcc
)?
答案 0 :(得分:7)
如果我能正确理解,你需要一个自启动的MPI可执行文件。正如我在评论中所写的那样,您可以使用一个特殊选项,使您的代码在提供时执行mpirun
,例如-launchmpi
。使用Open MPI,它更容易,因为它将特殊环境变量输出到已启动的MPI进程,例如OMPI_COMM_WORLD_RANK
。如果环境中存在此变量,那么您知道该程序是从mpirun
启动的,而不是直接启动的。您可以在一次检查中结合使用这两种方法:
int main (int argc, char **argv)
{
int perform_launch = 0;
// Scan argv[] for special option like "-launchmpi"
// and set perform_launch if found
if (perform_launch || getenv("OMPI_COMM_WORLD_RANK") == NULL)
{
// #args = argc + 3 ("mpirun -np 4" added) + NULL
// #args should be reduced by one if "-launchmpi" is present
char **args = (char **)calloc(
argc + (perform_launch ? 3 : 4),
sizeof(char *));
args[0] = "mpirun";
args[1] = "-np";
args[2] = "4";
// Copy the entire argv to the rest of args but skip "-launchmpi"
execvp("mpirun", args);
return EXIT_SUCCESS;
}
// Proceed as regular MPI code
MPI_Init(&argc, &argv);
...
// Magic happens here
...
MPI_Finalize();
return EXIT_SUCCESS;
}
如果您想控制MPI作业中的处理数量,您可以将其作为额外的控制提供,例如: -launchmpi 12
,或在环境变量中使用其值代替上述代码中的"4"
。
请注意,没有mpirun
通常无法启动MPI可执行文件。后者是MPI运行时的一个组成部分,它只需启动MPI可执行文件的多个副本。在使用任何MPI编译器包装器进行编译时,您也总是显式链接到MPI库(try mpicc -showme
)。虽然您可以静态链接MPI库(不推荐,请参阅here),但仍需要mpirun
才能运行MPI作业 - AFAIK无法嵌入mpirun
程序中的功能,至少不在Open MPI中。
答案 1 :(得分:1)
您可以使用bash脚本执行此操作:
# If you change this script has executable (chmod +x script_name) # and if you have the current path in the PATH variable (add export PATH=.:$PATH in your .bashrc) #Then, you can run this has: script_name program_args mpirun -np 4 your_executable_name "$@"