HPC SDK 容器指南

1. 简介

欢迎阅读 HPC SDK 容器文档。

本书旨在为您提供有关 NVIDIA HPC 应用程序容器的信息。

1.1. 容器简介

容器是一种基于 Linux 命名空间的轻量级虚拟化技术。与虚拟机不同,容器与主机共享内核和其他服务。因此,容器可以非常快速地启动,并且性能开销可忽略不计,但它们不提供虚拟机的完全隔离。

容器将整个应用程序用户空间环境捆绑到一个镜像中。这样,应用程序环境既可移植又一致,并且与底层主机系统软件配置无关。容器镜像可以广泛部署,甚至可以与他人共享,并确信结果是可重现的。

容器使开发人员、用户和系统管理员的生活更轻松。开发人员可以在容器中分发软件,以提供一致的运行时环境并减少支持开销。来自 NGC 等存储库的容器镜像可以帮助用户在任何系统上快速启动,并避免从源代码构建的复杂性。容器还可以帮助 IT 人员控制环境模块的复杂性,并支持不再与主机操作系统兼容的遗留工作负载。

有许多容器运行时;其中两个最重要的运行时是 Docker 和 Singularity,本指南都将介绍它们。

2. NGC

NVIDIA HPC SDK 容器 在 NGC 上可用,是开始使用 HPC SDK 和容器的最佳方式。提供两种类型的容器,“devel” 容器包含整个 HPC SDK 开发环境,“runtime” 容器仅包含重新分发使用 HPC SDK 构建的软件所需的组件。

2.1. 使用 Docker 访问 NGC 容器

在 “devel” 容器的 /opt/nvidia/hpc_sdk/$NVARCH/25.1/examples 中提供了几个源代码示例,其中 $NVARCHLinux_x86_64Linux_aarch64,具体取决于系统架构。

要在交互式会话中访问 OpenACC 示例,请使用

$ sudo docker run --gpus all -it --rm nvcr.io/nvidia/nvhpc:25.1-devel-cuda_multi-ubuntu22.04
# cd /opt/nvidia/hpc_sdk/Linux_x86_64/25.1/examples/OpenACC/samples
# make all

对于您自己的代码,以下命令将主机上的当前目录挂载为容器内的 /src,并以当前用户身份在容器内启动交互式会话。

$ sudo docker run --gpus all -it --rm --user $(id -u):$(id -g) --volume $(pwd):/src --workdir /src nvcr.io/nvidia/nvhpc:25.1-devel-cuda_multi-ubuntu22.04

由于容器是临时的,此命令将主机上的源代码目录挂载为容器内的 /src (--volume>),并在容器启动时默认进入此目录 (--workdir>)。从容器内部对源代码或构建工件所做的任何更改都将存储在主机上的源目录中,即使容器退出也会保留。

默认情况下,Docker 容器内的用户是 root--user 选项修改此设置,使容器内的用户与容器外的用户相同。如果没有此选项,在容器内的 /src 目录中创建的构建工件和其他文件将归 root 所有。

其他选项告诉 Docker 在容器退出时清理容器 (--rm>),启用 NVIDIA GPU (--gpus all>),以及这是一个交互式会话 (-it>)。

假设 /src 目录中有一个 Makefile,则可以附加 make 命令,以使用 HPC SDK 容器构建源代码,构建工件将在主机上的当前目录中可用。

$ sudo docker run --gpus all -it --rm --user $(id -u):$(id -g) --volume $(pwd):/src --workdir /src nvcr.io/nvidia/nvhpc:25.1-devel-cuda_multi-ubuntu22.04 make

2.2. 使用 Singularity 访问 NGC 容器

使用 Singularity 时,通常将容器镜像本地保存为 Singularity 镜像文件 (SIF)。此命令将容器保存在当前目录中,命名为 nvhpc-25.1-devel.sif。

$ singularity build nvhpc-25.1-devel.sif docker://nvcr.io/nvidia/nvhpc:25.1-devel-cuda_multi-ubuntu22.04

以下命令以当前用户身份在容器内启动交互式会话。

$ singularity shell --nv nvhpc-25.1-devel.sif

与 Docker 不同,Singularity 容器内的用户与容器外的用户相同,并且用户的 home 目录、当前目录和 /tmp 会自动挂载到容器内。

唯一需要的附加选项是 --nv,用于启用 NVIDIA GPU 支持。

假设当前目录中有一个 Makefile,则可以附加 make 命令,以使用 HPC SDK 容器构建源代码,构建工件将在主机上的当前目录中可用。

$ singularity exec --nv nvhpc-25.1-devel.sif make

3. 构建容器化应用

当交互式开发周期完成时,容器是广泛分发结果的绝佳方式。容器镜像从容器规范文件生成

  • Dockerfile 用于 Docker 和其他容器构建工具,

  • Singularity definition file 用于 Singularity。

Docker 和 Singularity 的指令集大致相同,但语法不同。

为了最大程度地减小容器镜像大小并遵守 HPC SDK 的允许重新分发,容器中应仅包含应用程序本身及其运行时依赖项。Docker 和 Singularity 都支持多阶段容器构建。多阶段容器规范通常由 2 部分组成

  1. 基于完整开发环境和应用程序源代码的构建阶段,以及

  2. 基于较小的运行时环境的分发阶段,该阶段从构建阶段中精选内容,例如应用程序二进制文件和其他构建工件。

CloverLeaf 迷你应用程序用于说明这些概念。

3.1. 使用 Docker 构建容器化应用

要使用 Docker 构建容器镜像

$ sudo docker build -t <name:tag> -f Dockerfile .

-t 选项指定容器镜像的名称,格式为 name:tag

CloverLeaf Dockerfile 的构建阶段基于来自 NGC 的 HPC SDK 开发镜像。运行时阶段基于较小的 HPC SDK 运行时镜像,也来自 NGC。HPC SDK 运行时镜像适用于与 HPC SDK 捆绑的每个 CUDA 版本;选择与用于构建 CloverLeaf 的 CUDA 版本相对应的版本。clover_leaf 二进制文件和示例输入数据集从构建阶段复制。

最后,为了方便起见,目录 /opt/CloverLeaf-OpenACC/bin 已添加到默认 PATH

# Build stage
FROM nvcr.io/nvidia/nvhpc:25.1-devel-cuda_multi-ubuntu22.04 AS build

# build CloverLeaf
RUN mkdir /source && \
    cd /source && \
    git clone https://github.com/UoB-HPC/CloverLeaf-OpenACC.git && \
    cd CloverLeaf-OpenACC && \
    make COMPILER=PGI FLAGS_PGI="-Mpreprocess -fast -acc -Minfo=acc -gpu=ccall -tp=px"

# Runtime stage
FROM nvcr.io/nvidia/nvhpc:25.1-runtime-cuda11.8-ubuntu22.04

COPY --from=build /source/CloverLeaf-OpenACC/clover_leaf /opt/CloverLeaf-OpenACC/bin/
COPY --from=build /source/CloverLeaf-OpenACC/InputDecks /opt/CloverLeaf-OpenACC/InputDecks

ENV PATH=/opt/CloverLeaf-OpenACC/bin:$PATH

要从此 Dockerfile 生成容器镜像

$ sudo docker build -t cloverleaf:git -f Dockerfile .

可以使用以下命令运行容器化的 CloverLeaf

$ sudo docker run --gpus all --cap-add=SYS_NICE --rm cloverleaf:git mpirun -n 1 --allow-run-as-root clover_leaf

注意

需要 --cap-add=SYS_NICE 以允许 MPI 设置 CPU 亲和性。

这将运行小型内置数据集;要使用其中一个示例数据集,请将其从主机挂载到工作目录 (/>) 中,命名为 clover.in

注意

数据集通常应从主机挂载到正在运行的容器中。将数据集包含在容器镜像中是不好的做法,不建议这样做。数据集可能很大,会膨胀容器镜像的大小,并且通常特定于特定用途。但是,这些条件都不适用于 CloverLeaf:CloverLeaf 输入文件很小,并且是标准的。

$ sudo docker run --gpus all --rm --volume $(pwd)/clover_bm32_short.in:/clover.in cloverleaf:git mpirun -n 1 --allow-run-as-root clover_leaf

3.2. 使用 Singularity 构建容器化应用

要使用 Singularity 构建容器镜像

$ sudo singularity build <image> Singularity.def

<image> 是生成的 Singularity 镜像文件 (SIF) 的名称。

构建 CloverLeaf 容器的说明实际上与上一节中相应的 Dockerfile 相同,尽管语法有所不同。主要区别在于配置容器环境的步骤;构建容器时,Singularity 不会自动设置从 Docker 基础镜像继承的环境,必须手动完成此操作。

# Build stage
BootStrap: docker
From: nvcr.io/nvidia/nvhpc:25.1-devel-cuda_multi-ubuntu22.04
Stage: build

%post
  . /.singularity.d/env/10-docker*.sh

  # build CloverLeaf
  mkdir /source
  cd /source
  git clone https://github.com/UoB-HPC/CloverLeaf-OpenACC.git
  cd CloverLeaf-OpenACC
  make COMPILER=PGI FLAGS_PGI="-Mpreprocess -fast -acc -Minfo=acc -gpu=ccall -tp=px"

# Runtime stage
BootStrap: docker
From: nvcr.io/nvidia/nvhpc:25.1-runtime-cuda11.8-ubuntu22.04

%files from build
  /source/CloverLeaf-OpenACC/clover_leaf /opt/CloverLeaf-OpenACC/bin/clover_leaf
  /source/CloverLeaf-OpenACC/InputDecks  /opt/CloverLeaf-OpenACC/InputDecks

%environment
  export PATH=/opt/CloverLeaf-OpenACC/bin:$PATH

要从此 Singularity definition file 生成容器镜像

$ sudo singularity build cloverleaf-git.sif Singularity.def

可以使用以下命令运行容器化的 CloverLeaf

$ singularity run --nv cloverleaf-git.sif mpirun -n 1 clover_leaf

这将运行小型内置数据集;要使用其中一个示例数据集,请将其复制到主机上的当前工作目录,命名为 clover.in。

$ cp CloverLeaf-OpenACC/InputDecks/clover_bm32_short.in clover.in
$ singularity run --nv cloverleaf-<label>.sif mpirun -n 1 clover_leaf

3.3. HPC 容器构建工具

CloverLeaf 就像几乎所有迷你应用程序一样,有意设计得非常简单,并且构建依赖项非常有限,本质上是一个编译器和一个 MPI 库。真实世界的应用程序通常要复杂得多,并且可能依赖于第三方软件组件。因此,容器化真实世界的应用程序可能比像 CloverLeaf 这样的迷你应用程序需要付出更多的努力。

HPC 容器构建工具 (HPCCM) 是一个开源工具,旨在简化容器规范文件的生成。HPCCM 从高级 Python 配方生成 Dockerfile 或 Singularity definition file。与“原生”容器规范格式相比,HPCCM 配方具有一些明显的优势。

  1. 一个 HPC 构建块库,它将容器镜像中包含的内容的选择与如何完成的细节分离开来。构建块透明地提供最新的组件和容器最佳实践。

  2. 与静态容器规范格式相比,Python 提供了更高的灵活性。基于 Python 的配方可以分支、验证用户输入等 - 同一个配方可以生成多个容器规范。

  3. 从同一个配方生成 Dockerfile 或 Singularity definition file。

以下是 HPCCM Python 配方,用于从 GitHub 存储库检出 CloverLeaf 的场景

# Build stage
Stage0 += baseimage(image='nvcr.io/nvidia/nvhpc:25.1-devel-cuda_multi-ubuntu22.04', _as='build')

# build CloverLeaf
Stage0 += generic_build(build=['make COMPILER=PGI FLAGS_PGI="-Mpreprocess -fast -acc -Minfo=acc -gpu=ccall -tp=px"'],
    install=['install -m 755 -d /opt/CloverLeaf-OpenACC/bin',
      'install -m 755 clover_leaf /opt/CloverLeaf-OpenACC/bin/clover_leaf',
      'install -m 755 -d /opt/CloverLeaf-OpenACC/InputDecks',
      'install -m 644 InputDecks/* /opt/CloverLeaf-OpenACC/InputDecks'],
    prefix='/opt/CloverLeaf-OpenACC',
    repository='https://github.com/UoB-HPC/CloverLeaf-OpenACC.git')

# Runtime stage
Stage1 += baseimage(image='nvcr.io/nvidia/nvhpc:25.1-runtime-cuda11.8-ubuntu22.04')

Stage1 += Stage0.runtime()
Stage1 += environment(variables={'PATH': '/opt/CloverLeaf-OpenACC/bin:$PATH'})

HPCCM 配方主要是描述性的,而不是像 Dockerfile 和 Singularity definition file 那样具有指令性。例如,该配方指定了 CloverLeaf git 存储库,但未定义应如何下载的详细信息。由于 CloverLeaf Makefile 未提供安装目标,因此需要指定基本的安装方法。HPCCM 还包括用于分别使用 GNU AutotoolsCMake 的软件包的 generic_autotoolsgeneric_cmake 构建块。

hpccm 命令行工具处理配方并输出 Dockerfile 或 Singularity definition file。生成的容器规范文件应按上述各节所示使用,以生成容器镜像。

$ hpccm --recipe cloverleaf.py

$ hpccm --recipe cloverleaf.py --format singularity --singularity-version 3.2

注意

多阶段容器构建已在 Singularity 3.2 版本中添加。但是,多阶段 Singularity definition file 语法与早期 Singularity 版本不兼容。HPCCM --singularity-version 标志目前是生成多阶段 Singularity definition file 所必需的;否则,输出是与所有版本兼容的单阶段 Singularity definition file。

HPCCM 包括许多常见 HPC 软件组件的构建块,例如 HDF5、FFTW、OpenMPI 以及真实世界应用程序可能需要的更多组件。其中一个构建块涵盖了 HPC SDK,使其易于包含在自定义镜像中。

4. 最佳实践

以下各节讨论使用 HPC SDK 容器时的一些最佳实践。

4.1. 多阶段构建

多阶段构建是控制容器镜像大小的一种方法。在同一个 Dockerfile 中,您可以定义第二个阶段,它是一个完全独立的容器镜像,并且仅将二进制文件和任何运行时依赖项从前面的阶段复制到该镜像中。多阶段构建的输出是与 Dockerfile 的最后阶段相对应的单个容器镜像。此方法也可用于防止源代码的重新分发。在前面的章节中已广泛使用多阶段构建。

4.2. 分层

Docker 使用的 OCI 镜像格式是分层的。OCI 容器镜像由一系列层组成。这些层按顺序应用,一层叠一层,形成您在运行容器时最终看到的容器镜像。

这些层会被缓存,Docker 容器构建工具可以利用层缓存来加速构建具有公共层的容器。此外,中断的构建可以从缓存中的上一个点恢复,而无需从头开始。

但是,在指定 Dockerfile 指令时必须小心,不要无意中膨胀容器镜像的大小。OCI 镜像规范采用文件级重复数据删除来处理冲突。当构建指令创建或修改文件时,整个文件都会保存在相应的层中。例如,以下 Dockerfile 指令生成七 (7) 个单独的层。

RUN mkdir /source
RUN cd /source && git clone https://github.com/UoB-HPC/CloverLeaf-OpenACC.git
RUN cd /source/CloverLeaf-OpenACC && make COMPILER=PGI FLAGS_PGI="-Mpreprocess -fast -acc -Minfo=acc -gpu=ccall -tp=px"
RUN mkdir -p /opt/CloverLeaf-OpenACC
RUN install -m 755 -d /opt/CloverLeaf-OpenACC/bin
RUN install -m 755 clover_leaf /opt/CloverLeaf-OpenACC/bin/clover_leaf
RUN install -m 755 -d /opt/CloverLeaf-OpenACC/InputDecks
RUN install -m 644 InputDecks/* /opt/CloverLeaf-OpenACC/InputDecks
RUN rm -rf /source/CloverLeaf-OpenACC

尽管最终指令是删除 CloverLeaf 源代码的 git 检出,但源代码实际上仍然存在于镜像中 — 最后一层只是一个白化文件条目。

从层的文件级重复数据删除中得出的最佳实践是将所有修改同一组文件的操作放在同一 Dockerfile 指令中。例如,在创建临时文件的同一指令中删除任何临时文件。通常,将与同一组件相关的所有指令放在同一层中,但对不同的组件使用单独的层。HPCCM 自动生成遵循此最佳实践的容器规范文件。

4.3. 多架构支持

容器化应用程序的目标之一是使其能够在各种系统上运行,包括跨不同的 CPU 和 GPU 代。但是,CloverLeaf Makefile 将 GPU 计算能力设置为 cc60,即 Pascal。默认的 CloverLeaf 二进制文件可能无法在较旧或较新的 GPU 上运行。同样,NVIDIA 编译器隐式地针对构建系统 CPU 架构进行了优化。如果容器是在具有最新 CPU 微架构的系统上构建的,则它将无法在具有较旧 CPU 的系统上运行,反之,如果在具有较旧 CPU 微架构的系统上构建,则它可能无法在较新的 CPU 上最佳运行。

一种解决支持各种系统和提供最佳性能之间紧张关系的方法是构建 *胖* 或 *统一* 二进制文件。对多种计算能力和指令集的支持可以嵌入到单个二进制文件中,并且将在运行时自动使用最佳代码路径。这是通过指定 -gpu=ccall 编译器选项所采用的方法,该选项将在同一二进制文件中为多种 GPU 计算能力生成代码。

另一种方法是为“最低公分母”构建。这是通过指定 -tp=px 编译器选项为 CPU 微架构采用的方法。

不幸的是,某些真实世界应用程序的构建系统不允许使用统一的二进制方法。另一种选择是在同一容器镜像中构建和重新分发多个二进制文件。可以使用容器入口点来检测运行时的系统架构,并相应地设置容器内的环境 (PATHLD_LIBRARY_PATH 等)。由于 HPCCM 配方是 Python,因此构建多个二进制文件就像一个 for 循环一样简单。例如,要为多种 CPU 架构构建

for cpu_arch in ['sandybridge', 'haswell', 'skylake', 'icelake']:
  Stage0 += generic_build(build=['make COMPILER=PGI FLAGS_PGI="-Mpreprocess -fast -acc -Minfo=acc -ta=tesla,ccall -tp={}"'.format(cpu_arch)],
        install=['install -m 755 -d /opt/CloverLeaf-OpenACC-{}/bin'.format(cpu_arch),
            'install -m 755 clover_leaf /opt/CloverLeaf-OpenACC-{}/bin'.format(cpu_arch)],
        prefix='/opt/CloverLeaf-OpenACC-{}'.format(cpu_arch),
        repository='https://github.com/UoB-HPC/CloverLeaf-OpenACC.git')

通常,相同的配方也可以用于不同的处理器架构。HPC SDK NGC 容器同时为 Arm 和 X86 处理器提供。对 -tp px 编译器选项进行细微调整后,提供的 Dockerfile、Singularity definition file 和 HPCCM 配方也可用于生成 Arm 容器镜像。

4.4. 版本标记和可重现性

容器规范文件通常从 GitHub 等在线存储库下载内容。该内容可能会随着时间的推移而发生变化。例如,CloverLeaf GitHub 存储库的 master 分支可能会以使容器规范无效的方式更改。为了避免这种情况,请指定标签或提交,以确保容器镜像构建是可重现的

HPCCM 配方可以检出特定的提交或标签,以提高配方的可重现性。

Stage0 += generic_build(build=['make COMPILER=PGI FLAGS_PGI="-Mpreprocess -fast -acc -Minfo=acc -gpu=ccall -tp=px"'],
    commit='23b8e81b5234474757e44418e78ce91c8d050363',
    install=['install -m 755 -d /opt/CloverLeaf-OpenACC/bin',
        'install -m 755 clover_leaf /opt/CloverLeaf-OpenACC/bin/clover_leaf',
        'install -m 755 -d /opt/CloverLeaf-OpenACC/InputDecks',
        'install -m 644 InputDecks/* /opt/CloverLeaf-OpenACC/InputDecks'],
    prefix='/opt/CloverLeaf-OpenACC',
    repository='https://github.com/UoB-HPC/CloverLeaf-OpenACC.git')

通知

注意

所有 NVIDIA 设计规范、参考板、文件、图纸、诊断程序、列表和其他文档(统称为“材料”,无论整体还是单独)均按“原样”提供。NVIDIA 对材料不做任何明示、暗示、法定或其他方面的保证,并明确声明对不侵权、适销性和针对特定用途的适用性的所有暗示保证。

所提供的信息被认为是准确和可靠的。但是,NVIDIA 公司对使用此类信息造成的后果或因使用此类信息而可能导致的任何侵犯第三方专利或其他权利的行为不承担任何责任。NVIDIA 公司未以暗示或其他方式授予任何专利权许可。本出版物中提及的规范如有更改,恕不另行通知。本出版物取代并替换之前提供的所有其他信息。未经 NVIDIA 公司明确书面批准,NVIDIA 公司产品不得用作生命支持设备或系统中的关键组件。

商标

NVIDIA、NVIDIA 徽标、CUDA、CUDA-X、GPUDirect、HPC SDK、NGC、NVIDIA Volta、NVIDIA DGX、NVIDIA Nsight、NVLink、NVSwitch 和 Tesla 是 NVIDIA Corporation 在美国和其他国家/地区的商标和/或注册商标。其他公司和产品名称可能是与其相关的各自公司的商标。