4.8. 必需的支撑库

虽然Open MPI可以构建支持多种系统,但在任何环境中构建Open MPI都需要一小部分必需的支持库。其中几个软件包既是Open MPI运行的基础,又并非在所有环境中普遍可用。因此,这些"基础"软件包既被嵌入到Open MPI的分发包中,又直接整合到Open MPI的配置、构建和安装流程中。

参见下方了解 Open MPI如何选择使用这些软件包的嵌入式版本 还是系统已安装的版本。

  • 硬件位置感知

    • 此库为必需项;若无此库,Open MPI将无法构建。

    • 最低要求版本: 1.11.0

      注意

      虽然最低版本的Hwloc可以运行,但与后续版本相比,它可能存在缺陷和/或功能较少。

      除了关于v3.0.0及更高版本的Hwloc限制(见下文),Open MPI社区通常建议使用最新可用的Hwloc版本,除非有特定原因不这样做。

    • Open MPI 发行版中嵌入的版本: 2.7.1

    危险

    截至v5.0.x版本,Open MPI尚未支持Hwloc v3.x系列(在Open MPI v5.0.x发布时该版本可能尚未推出)。与Hwloc v2.x系列相比,预计Hwloc v3.x会破坏API和/或ABI兼容性。

    如果发现系统中已安装的外部Hwloc版本≥v3.0.0,Open MPI将拒绝构建。这是基于其他HPC应用程序和/或库可能正在使用该版本的假设。此类配置可能导致Open MPI应用程序出现难以排查且可能令人困惑的运行时故障。

    如果Open MPI的configure脚本因检测到Hwloc安装版本≥v3.0.0而中止,您可以通过以下两种方式解决:确保Open MPI找到LD_LIBRARY_PATH中的路径顺序),或强制使用Open MPI捆绑的Hwloc:

    shell$ ./configure --with-hwloc=internal ...
    

    无论如何,至关重要的一点是,如果MPI应用程序或其任何依赖项使用了Hwloc,那么它必须使用与编译Open MPI时相同的Hwloc版本。

  • Libevent

    • 此库为必需项;没有它,Open MPI将无法构建。

    • 最低版本要求: 2.0.21

    • Open MPI发行版中嵌入的版本: 2.1.12

      注意

      Open MPI社区已对Libevent 2.1.12进行了大量测试。其他版本应该可以工作,但——与Hwloc、OpenPMIx和PRRTE不同——没有太多理由升级使用更高版本的Libevent。

  • OpenPMIx

    • 该库是必需的;没有它,Open MPI将无法构建。

    • 在不使用PRRTE构建时所需的最低版本: 4.2.0

      注意

      虽然最低版本的OpenPMIx可以运行,但相比后续版本可能存在更多缺陷和/或功能较少。

      Open MPI社区通常建议使用最新可用的OpenPMIx版本,除非有特殊原因不能使用。

      注意

      虽然OpenPMIx是实现PMIx标准软件的正规名称,但在本文档中广泛使用"PMIx"一词来指代OpenPMIx软件包。

    • 使用PRRTE构建时的最低版本要求: 参见PRRTE项目文档

    • Open MPI 发行版中嵌入的版本: v5.0.8a1

  • PRRTE

    • 在某些环境中,此库是可选的。请参阅下文。

    • 最低要求版本: 3.0.0

      注意

      虽然PRRTE的最低版本可以运行,但与后续版本相比,它可能仍存在缺陷和/或功能较少。例如,如果您使用3.0.0版本构建和运行,将无法获得完整的mpirun(1)手册页。

      Open MPI社区通常建议使用PRRTE的最新可用版本,除非有特殊原因不能使用。

    • Open MPI 发行版中嵌入的版本: v3.0.11a1

    PRRTE 提供了 Open MPI 功能齐全的 mpirun / mpiexec MPI 应用程序启动器(这两个命令是相同的;它们是同一可执行文件的符号链接)。

    警告

    如果您正在构建嵌入在Open MPI v5.0.x发行版中的PRRTE:

    • 如果您同时也在构建嵌入在Open MPI v5.0.x发行版中的PMIx,这种软件包组合是受支持的。

    • 如果您正在针对外部PMIx安装进行构建(即非嵌入在Open MPI v5.0.x发行版中的PMIx版本),您应查阅PRRTE项目文档以了解所需的最低PMIx版本。

    • 如果您的环境使用其他MPI应用程序启动器(例如,Slurm用户可以使用srun启动器来"直接启动"Open MPI应用程序),那么使用PRRTE是可选的。

    • 如果您的环境中没有其他MPI应用程序启动器,那么您需要安装PRRTE并构建支持PRRTE的Open MPI。

    • Open MPI可以使用其源代码树中嵌入的PRRTE副本,也可以针对外部PRRTE安装进行编译/链接。有关如何指定每种方法的详细信息,请参阅本节

注意

一般来说,Open MPI社区建议同时使用最新版本的必需支持库和所有其他可选支持库。这是因为较新版本通常包含错误修复,有时会影响Open MPI的功能。具体来说,在配备英特尔Ponte Vecchio加速器的系统上,使用早于v2.8.0版本的硬件位置感知库存在已知问题。若在此类系统上运行Open MPI,必须使用Hwloc v2.8.0或更新版本,否则可能出现未定义行为。这种现象并非硬件位置感知库独有,因此Open MPI社区建议尽可能使用所有支持库的最新版本。

4.8.1. 库依赖项

这些支持库彼此之间存在依赖关系:

../_images/required-support-libraries-dependency-graph.png

Open MPI所需的支持库依赖关系图。

上层模块依赖于下层模块。具体来说:

  • Open MPI依赖于PRRTE、PMIx、Hwloc和Libevent(即所有组件)。

  • PRRTE依赖于PMIx、Hwloc和Libevent(即除Open MPI之外的所有组件)。

  • PMIx 依赖于 Hwloc 和 Libevent。

  • Hwloc 不依赖任何其他组件。

  • Libevent 不依赖任何其他组件。

在运行时,关键的是运行时链接器必须加载这些库中的每一个的精确一份副本

注意

所需的支持库可能还有其他依赖项,但为了简洁以及与构建Open MPI的相关性,此处不讨论其他依赖项。

4.8.2. 潜在问题

如果单个进程中加载了上述共享库的多个不同副本,可能会(将会)出现问题。例如,考虑以下情况:

  • 加载Open MPI共享库会导致加载Libevent共享库vA.B.C.

  • 但随后加载PMIx共享库会导致加载Libevent共享库vX.Y.Z。

由于现在同一个进程中加载了两个不同版本的Libevent共享库(是的,这种情况确实会发生!),可能会出现(必将出现)不可预测的行为。

这种基本错误场景可能存在许多变体。它们都很糟糕,且可能极难诊断。

4.8.3. 避免问题

避免这些问题的一个简单方法是配置您的系统,使其仅保留每个必需支持库的一个副本。

重要

如果可能,在调用Open MPI的configure脚本之前,请尽量使用操作系统/环境中的包管理器安装这些支持库(包括它们的开发头文件)。

并非所有的包管理器都提供所有必需的支撑库。但即使您的包管理器仅安装了——例如——Libevent和Hwloc,这也在一定程度上简化了最终的Open MPI配置,从而避免了一些潜在的配置错误。

4.8.4. configure如何查找所需的库

为了在最终用户便利性和灵活性之间取得平衡,Open MPI在其官方发布包中捆绑了这四个必需的支持库。

通常情况下,如果Open MPI无法找到所需的支持库,它会作为主Open MPI配置、构建和安装流程的一部分,自动配置、构建、安装并使用其捆绑版本。

换句话说:Open MPI的configure脚本会检查构建机器,查看是否能找到每个所需的支持头文件和库。如果找不到,它将尝试回退并使用对应的捆绑支持库。

重要

请注意,configure足够智能,能够理解所需支持库之间的依赖关系。

具体来说:如果configure检测到系统中已安装某个支持库的开发头文件和库文件,那么它将忽略对应的捆绑支持库,同时也会忽略依赖关系图中位于该库下方的所有其他捆绑支持库。

4.8.4.1. 构建示例1

configure/usr/local 目录中找到 PRRTE 的开发头文件和库文件。这将导致以下情况发生:

  1. configure 将忽略Open MPI源代码树中捆绑的PRRTE库,转而使用已安装在/usr/local中的PRRTE。

  2. configure 也会忽略 Open MPI 源代码树中捆绑的 PMIx、Hwloc 和 Libevent 库。

    • 如果configure在构建机器上无法找到PMIx、Hwloc和Libevent的头文件和库(即假设与/usr/local中PRRTE使用的PMIx、Hwloc和Libevent相同),这将导致错误:configure会中止,因此拒绝构建Open MPI。

4.8.4.2. 构建示例 2

configure 在构建机器上没有找到PRRTE,但确实/opt/local中找到了PMIx的开发头文件和库。这将导致以下情况发生:

  1. configure 将配置构建捆绑在Open MPI源代码树中的PRRTE库。

  2. configure 将忽略 Open MPI 源代码树中捆绑的 PMIx 库,转而使用已安装在 /opt/local 中的 PMIx。

  3. configure 也会忽略 Open MPI 源代码树中捆绑的 Hwloc 和 Libevent 库。

    • 如果configure无法在构建机器的其他位置找到Hwloc和Libevent的头文件和库(即假设与/opt/local中PMIx使用的Hwloc和Libevent相同),这将导致错误:configure会中止,因此拒绝构建Open MPI。

4.8.4.3. 构建示例3

configure 仅能在构建机器上找到 Libevent 的开发头文件和库文件。这将导致以下情况发生:

  1. configure 将配置用于构建捆绑在Open MPI源代码树中的PRRTE、PMIx和Hwloc库。

  2. configure 将忽略Open MPI源代码树中捆绑的Libevent库,转而使用已安装的Libevent版本。

4.8.5. C与Fortran的难点

有时在尝试构建Open MPI时,您可能会看到类似以下的错误:

...
PPFC     profile/pwin_unlock_f08.lo
PPFC     profile/pwin_unlock_all_f08.lo
PPFC     profile/pwin_wait_f08.lo
FCLD     libmpi_usempif08.la
ld: library not found for -lhwloc
collect2: error: ld returned 1 exit status
make``2``: *** ``libmpi_usempif08.la`` Error 1

当多种因素同时出现时,可能会发生此错误:

  1. 如果Open MPI的configure脚本选择使用"外部"安装的hwloc和/或Libevent(即位于Open MPI源代码树之外)。

  2. 如果Open MPI的configure脚本选择了来自不同套件/安装的C和Fortran编译器。

简而言之:如果C和Fortran编译器套件的默认搜索库路径不同,C链接器可能会找到系统安装的libhwloc和/或libevent,但Fortran链接器可能找不到。

从Open MPI v4.0.0版本开始,在Mac OS系统上这种情况可能会更频繁地发生,原因是:

  1. 在v4.0.0版本中,Open MPI的configure脚本被修改为"优先"使用系统安装的hwloc和Libevent版本(而不是优先使用Open MPI发行版tarball中捆绑的hwloc和Libevent)。

  2. 在MacOS系统中,通常通过HomebrewMacPorts进行安装:

例如,截至2019年7月,Homebrew:

  • /usr/local 目录下安装 hwloc v2.0.4

  • /usr/local目录下安装Gnu C和Fortran编译器套件v9.1.0。但需要注意的是,C编译器可执行文件名为gcc-9(而非gcc!),而Fortran编译器可执行文件名为gfortran

综合考虑这些因素后,Open MPI的configure脚本会做出以下决定:

  • C编译器是gcc(这是MacOS系统自带的C编译器)。

  • Fortran编译器是gfortran(这是通过Homebrew安装的Fortran编译器)。

  • /usr/local目录中存在一个合适的系统安装的hwloc,C编译器/链接器无需指定任何额外的链接器搜索路径即可找到它。

细心的读者会发现,C和Fortran编译器来自两个完全不同的安装环境。实际上,它们的默认库搜索路径也不同:

  • MacOS系统安装的gcc默认会搜索/usr/local/lib目录。

  • 通过Homebrew安装的gfortran默认情况下不会搜索/usr/local/lib目录。

因此,由于Open MPI的大部分源代码库是用C语言编写的,它能够成功编译/链接hwloc。但当编译和链接Open MPI的Fortran代码(针对mpi_f08模块)时,通过Homebrew安装的gfortran——默认情况下不会搜索/usr/local/lib目录——无法找到libhwloc库,导致链接失败。

针对这个问题,有几种可能的解决方案:

  1. 最佳解决方案是始终确保Open MPI使用来自同一套件/安装的C和Fortran编译器。这将确保两个编译器/链接器使用相同的默认库搜索路径,所有行为应保持一致。例如,以下命令指示Open MPI的configure脚本使用gcc-9作为C编译器(截至2019年7月,这是Homebrew安装的C编译器的可执行文件名):

    shell$ ./configure CC=gcc-9 ...
    
    # 您可以精确指定C编译器的绝对路径,和/或同时指定Fortran编译器:
    shell$ ./configure CC=/usr/local/bin/gcc-9 FC=/usr/local/bin/gfortran ...
    

    请注意,这可能会导致configure无法找到Homebrew安装的hwloc,转而使用Open MPI源代码树中捆绑的hwloc。

  2. 或者,您可以强制configure选择捆绑版本的hwloc和libevent,从而完全避免此问题:

    shell$ ./configure --with-hwloc=internal --with-libevent=internal ...
    
  3. 最后,你可以明确告诉configure在哪里查找外部hwloc库。不过这样做可能会产生一些意外后果,因为它会将C和Fortran链接器的默认搜索路径前缀都设置为/usr/local/lib

    shell$ ./configure --with-hwloc-libdir=/usr/local/lib ...
    

4.8.6. 覆盖configure行为

如果configure的默认搜索行为不能满足您的环境需求,您可以使用命令行选项来覆盖其默认行为

例如,如果PMIx和/或PRRTE的安装位置不在默认头文件与链接器搜索路径范围内,您可以通过命令行选项告知Open MPI的configure脚本搜索位置。以下示例展示了当PMIx和PRRTE都安装在/opt/open-mpi-stuff目录时的configure调用方式:

./configure --prefix=$HOME/openmpi-install \
    --with-pmix=/opt/open-mpi-stuff \
    --with-prrte=/opt/open-mpi-stuff ...

再举一个例子,如果您没有root权限使用操作系统/环境包管理器,并且您的MPI应用程序较为简单(例如没有外部库依赖),您可能希望这样配置Open MPI:

./configure --prefix=$HOME/openmpi-install \
    --with-libevent=internal --with-hwloc=internal \
    --with-pmix=internal --with-prrte=internal ...

internal 关键字强制 configure 使用所有四个捆绑版本的必需库。

危险

在覆盖configure对这些库的默认搜索行为时,务必非常非常小心。请牢记关键要求:Open MPI基础设施和应用程序必须加载每个支持库的唯一副本。为简单起见,最好确保使用与Open MPI编译构建时完全相同的支持库。

例如,使用上述示例configure命令安装的Open MPI时,您可能需要在运行时链接器搜索路径(如Linux上的LD_LIBRARY_PATH)前添加$HOME/openmpi-install/lib。这将确保链接器能够找到您Open MPI安装目录中的四个支持库,即使系统中其他地方存在相同支持库的其他副本。

4.8.7. 给打包者的(强烈)建议

如果您是Open MPI的打包人员,我们强烈建议您的Open MPI软件包不应包含Hwloc、Libevent、PMIx或PRRTE。相反,它应该依赖于这些软件包的外部独立构建版本。

更多详情请参阅打包者建议部分