10.12. 故障排除

启动MPI作业可能是一个涉及多个环节的复杂过程。本节旨在为用户遇到的一些最常见问题提供解决方案。

10.12.1. 关于缺失符号的消息

Open MPI在运行时加载大量插件(有时称为“组件”或“模块”)。有时插件可能因无法解析所需的所有符号而加载失败。发生这种情况的原因有几个。

  • 该插件适用于不同版本的Open MPI。参见此部分了解Open MPI可能尝试打开“错误”插件的原因说明。

  • 一个应用程序正尝试在私有符号空间中手动动态打开libmpi。例如,如果应用程序没有链接到libmpi,而是调用类似以下的代码:

    /* This is a Linux example |mdash| the issue is similar/the same on other
       operating systems */
    handle = dlopen("libmpi.so", RTLD_NOW | RTLD_LOCAL);
    

    这是由于一些运行时链接器的深层魔法——在这篇Open MPI开发者列表的帖子末尾有相关讨论。 简而言之,问题如下:

    1. 动态库 libmpi 在"本地"符号空间中打开。

    2. MPI_INIT 被调用,该函数尝试加载 Open MPI 的插件。

    3. Open MPI的插件依赖于libmpi(以及其他Open MPI支持库)中的符号;这些符号必须在加载插件时解析。

    4. 然而,由于libmpi是在"本地"符号空间中打开的,其符号对它所打开的插件不可用。

    5. 因此,由于无法解析所有符号,插件加载失败,并显示相应的警告信息。

    遗憾的是,这个问题的最终解决方案比Open MPI本身更复杂——它实际上是一个POSIX标准层面的问题(如上方开发邮件列表帖子中简要所述)。

    不过,有几种常见的变通方法:

    • 在公共/全局符号作用域中动态打开libmpi——而非私有/局部作用域。这将使得当Open MPI动态加载其插件时,libmpi的符号可用于解析。

    • 如果libmpi作为某些底层框架的一部分被打开,且无法将其私有/局部作用域更改为公共/全局作用域,则应在调用底层框架之前,先在公共/全局作用域中动态打开libmpi。这听起来有点粗糙(确实如此),但至少运行时链接器足够智能,不会重复加载libmpi——不过它确实会将libmpi保持在公共作用域中。

    • 使用Open MPI的configure脚本中的--disable-dlopen--disable-mca-dso选项(有关这些选项的更多详情,请参阅TODO NONEXISTENT FAQ条目)。这些选项会将Open MPI的所有插件合并到libmpi中——这意味着插件实际上位于libmpi内,而不会在运行时动态加载。

    • 通过使用--disable-shared--enable-static配置Open MPI,将其构建为静态库。这与--disable-dlopen效果相同,但同时会生成libmpi.a(而非共享库)。

10.12.2. 关于缺失库的错误

在使用库文件位于非默认搜索路径位置的编译器构建Open MPI时,如果相应的环境未正确设置,在尝试启动MPI应用程序时可能会看到关于这些编译器支持库的错误。

例如,您可能会看到类似以下的警告:

# With the Intel compiler suite
shell$ mpirun -n 1 --host node1.example.com mpi_hello
prted: error while loading shared libraries: libimf.so: cannot open shared object file: No such file or directory
--------------------------------------------------------------------------
A daemon (pid 11893) died unexpectedly with status 127 while
attempting to launch so we are aborting.
...more error messages...

# With the PGI compiler suite
shell$ mpirun -n 1 --host node1.example.com mpi_hello
prted: error while loading shared libraries: libpgcc.so: cannot open shared object file: No such file or directory
...more error messages...

# With the PathScale compiler suite
shell$ mpirun -n 1 --host node1.example.com mpi_hello
prted: error while loading shared libraries: libmv.so: cannot open shared object file: No such file or directory
...more error messages...

具体来说,Open MPI首先尝试在node1.example.com上启动一个"辅助"守护进程prted,但由于未能找到prted依赖的某个库而失败。上面显示的库(libimf.solibpgcc.solibmv.so)分别对应特定的编译器套件(Intel、PGI和PathScale)。因此,很可能是用户未在该节点上正确设置编译器库环境。

请再次确认您已在目标节点上为交互式和非交互式登录设置了适当的编译器环境。

注意

一个常见错误是确保编译器环境为交互式登录正确设置,但未为非交互式登录进行设置。

以下是一个用户编译的MPI应用程序示例,它在本地运行良好,但在远程节点上非交互式调用时失败:

# Compile a trivial MPI application
head_node$ cd $HOME
head_node$ mpicc mpi_hello.c -o mpi_hello

# Run it locally; it works fine
head_node$ ./mpi_hello
Hello world, I am 0 of 1.

# Run it remotely interactively; it works fine
head_node$ ssh node2.example.com

Welcome to node2.
node2$ ./mpi_hello
Hello world, I am 0 of 1.
node2$ exit

# Run it remotely *NON*-interactively; it fails
head_node$ ssh node2.example.com $HOME/mpi_hello
mpi_hello: error while loading shared libraries: libimf.so: cannot open shared object file: No such file or directory

遇到这种情况时,请检查您的shell脚本启动文件,并确保为非交互式登录正确设置了适当的编译器环境。

10.12.3. 跨多主机运行时的问题

当您能够在单台主机上运行MPI作业,但无法在多台主机上运行时,请尝试以下方法:

  1. 确保您的启动器能够在多台主机上启动。例如,如果您使用ssh,请尝试ssh连接到每台远程主机,并确保不会提示输入密码。例如:

    shell$ ssh remotehost hostname
    remotehost
    

    如果您无法在多台主机上启动,请检查您的SSH密钥是否设置正确。或者,如果您在托管环境中运行,例如Slurm、Torque或其他作业启动器,请检查您是否预留了足够的主机,是否在分配的作业中运行等。

  2. 确保在您尝试运行的每个远程主机上正确设置了PATHLD_LIBRARY_PATH。例如,使用ssh时:

    shell$ ssh remotehost env | grep -i path
    PATH=...远程主机上的路径...
    LD_LIBRARY_PATH=...远程主机上的LD库路径...
    

    如果您的PATHLD_LIBRARY_PATH未正确设置,请参阅本节获取正确的值。请注意,一台机器上可以安装多个Open MPI;PATHLD_LIBARY_PATH找到的第一个Open MPI安装才是有效的。

  3. 在多个主机上运行一个简单的非MPI任务。这可以验证Open MPI运行时系统在多个主机上是否正常运行。例如,尝试运行hostname命令:

    shell$ mpirun --host remotehost hostname
    remotehost
    shell$ mpirun --host remotehost,otherhost hostname
    remotehost
    otherhost
    

    如果您无法在多个主机上运行非MPI作业,请检查以下常见问题:

    1. 检查每个远程主机上的非交互式shell设置,确保其正确配置了PATHLD_LIBRARY_PATH

    2. 检查Open MPI是否在远程主机上找到并启动了正确版本的Open MPI。

    3. 确保主机之间已禁用防火墙(OpenMPI会在单个MPI作业中的主机之间打开随机TCP端口,有时还会打开随机UDP端口)。

    4. 尝试使用级别为10的plm_base_verbose MCA参数运行,这将启用额外的调试输出来查看Open MPI如何在远程主机上启动。例如:

      mpirun --mca plm_base_verbose 10 --host remotehost hostname``
      
  4. 现在运行一个不涉及MPI通信的简单MPI作业,跨越多台主机。Open MPI发行版中examples目录下的hello_c程序是个不错的选择。这可以验证MPI子系统能否正确初始化和终止。例如:

    shell$ mpirun --host remotehost,otherhost hello_c
    Hello, world, I am 0 of 1, (Open MPI VERSION, package: Open MPI jsquyres@example.com Distribution, ident: VERSION, DATE)
    Hello, world, I am 1 of 1, (Open MPI VERSION, package: Open MPI jsquyres@example.com Distribution, ident: VERSION, DATE)
    

    如果无法运行简单的非通信MPI作业,这可能表明您的Open MPI安装无法在远程主机上正确初始化。请仔细检查远程主机上的非交互式登录设置。

  5. 现在在多台主机上运行一个简单的MPI作业,进行基本的MPI通信。Open MPI发行版中examples目录下的ring_c程序是个不错的选择。这可以验证MPI子系统是否能够通过网络传递MPI流量。例如:

    shell$ mpirun --host remotehost,otherhost ring_c
    Process 0 sending 10 to 0, tag 201 (1 processes in ring)
    Process 0 sent to 0
    Process 0 decremented value: 9
    Process 0 decremented value: 8
    Process 0 decremented value: 7
    Process 0 decremented value: 6
    Process 0 decremented value: 5
    Process 0 decremented value: 4
    Process 0 decremented value: 3
    Process 0 decremented value: 2
    Process 0 decremented value: 1
    Process 0 decremented value: 0
    Process 0 exiting
    

    如果无法在多台主机上运行简单的MPI作业,这可能表明Open MPI尝试用于MPI通信的网络存在问题。尝试限制其使用的网络,和/或探索您正在使用的通信模块的1到3级MCA参数。例如,如果您使用的是TCP BTL,请查看以下命令的输出:

    ompi_info --level 3 --param btl tcp