构建一个支持GPU的Conda环境用于Horovod

在本节中,我们将介绍如何为深度学习项目构建Conda环境,使用Horovod实现跨多个GPU(无论是在同一节点上还是分布在多个节点上)的分布式训练。

安装NVIDIA CUDA工具包

安装 NVIDIA CUDA Toolkit 10.1 (文档),这是目前Horovod支持的所有三个深度学习框架都支持的最新版本的NVIDIA CUDA Toolkit。

为什么不直接使用 cudatoolkit 包?

通常在使用Conda安装支持GPU的PyTorch、TensorFlow或Apache MXNet时,您需要将适当版本的cudatoolkit包添加到environment.yml文件中。 不幸的是,至少目前来说,通过Conda可用的cudatoolkit包不包含NVIDIA CUDA编译器(NVCC),而构建针对PyTorch、TensorFlow或MXNet的Horovod扩展需要此编译器。

关于cudatoolkit-dev包有什么要注意的?

虽然conda-forge提供了包含NVCC的cudatoolkit-dev软件包, 但我们发现这些软件包难以持续稳定地正确安装。部分可用版本需要手动干预以接受许可协议, 这使得这些版本不适合在远程系统上安装(这是关键功能)。其他版本似乎在Ubuntu上可用, 但在其他Linux发行版上无法正常工作。

尽管如此,我们仍建议您尝试将 cudatoolkit-dev 添加到您的 environment.yml 文件中,看看会发生什么!该软件包维护良好,因此未来可能会变得更加稳定。

使用 nvcc_linux-64 元包

最稳健的方法来获取NVCC并仍使用Conda管理所有其他依赖项 是在您的系统上安装NVIDIA CUDA Toolkit,然后从conda-forge安装一个元包 nvcc_linux-64,它会配置您的Conda环境以使用系统上安装的NVCC 以及Conda环境内安装的其他CUDA Toolkit组件。

environment.yml 文件

我们更倾向于在Conda environment.yml 文件中指定尽可能多的依赖项, 并且仅在 requirements.txt 中指定那些无法通过Conda渠道获取、需要通过 pip 安装的依赖项。 有关所需依赖项的详细信息,请查阅Horovod 安装指南

通道优先级

使用推荐的通道优先级。请注意,conda-forge 的优先级高于 defaults,而 pytorch 的优先级高于 conda-forge

name: null

channels:
- pytorch
- conda-forge
- defaults

依赖项

关于依赖项,有几点值得注意。

  1. 尽管您已手动安装了NVIDIA CUDA工具包,但仍应使用Conda来管理其他必需的CUDA组件,例如cudnnnccl(以及可选的cupti)。

  2. 使用两个元包,cxx-compilernvcc_linux-64,以确保安装了合适的C和C++编译器,并且生成的Conda环境能够识别手动安装的CUDA工具包。

  3. Horovod 需要某些控制器库来协调各个 Horovod 进程之间的工作。通常这会是某些 MPI 实现,例如 OpenMPI。然而,与其直接指定 openmpi 包,您应该选择 mpi4py Conda 包,它提供了支持 CUDA 的 OpenMPI 构建版本。

  4. Horovod 还支持 Gloo 集体通信库,可用于替代 MPI。包含 cmake 以确保构建 Horovod 的 Gloo 扩展。

以下是核心必需依赖项。完整的 environment.yml 文件可在 GitHub 上获取。

dependencies:
- bokeh=1.4
- cmake=3.16 # insures that Gloo library extensions will be built
- cudnn=7.6
- cupti=10.1
- cxx-compiler=1.0 # insures C and C++ compilers are available
- jupyterlab=1.2
- mpi4py=3.0 # installs cuda-aware openmpi
- nccl=2.5
- nodejs=13
- nvcc_linux-64=10.1 # configures environment to be "cuda-aware"
- pip=20.0
- pip:
    - mxnet-cu101mkl==1.6.* # MXNET is installed prior to horovod
    - -r file:requirements.txt
- python=3.7
- pytorch=1.5
- tensorboard=2.1
- tensorflow-gpu=2.1
- torchvision=0.6

requirements.txt 文件

requirements.txt 文件是列出所有 pip 依赖项(包括 Horovod 本身)以供安装的地方。除了 Horovod,我们通常还会使用 pip 安装 JupyterLab 扩展,以通过 jupyterlab-nvdashboard 启用 GPU 和 CPU 资源监控,并通过 jupyter-tensorboard 支持 Tensorboard。

horovod==0.19.*
jupyterlab-nvdashboard==0.2.*
jupyter-tensorboard==0.2.*

# make sure horovod is re-compiled if environment is re-built
--no-binary=horovod

注意文件末尾使用了--no-binary选项。包含此选项可确保每当Conda环境重新构建时,Horovod都会重新构建。

构建Conda环境

在将需要通过Conda下载的所有必要依赖项添加到 environment.yml 文件,以及需要通过 pip 下载的所有依赖项添加到 requirements.txt 文件后,通过运行以下命令在项目目录的子目录 env 中创建Conda环境。

$ export ENV_PREFIX=$PWD/env
$ export HOROVOD_CUDA_HOME=$CUDA_HOME
$ export HOROVOD_NCCL_HOME=$ENV_PREFIX
$ export HOROVOD_GPU_OPERATIONS=NCCL
$ conda env create --prefix $ENV_PREFIX --file environment.yml --force

默认情况下,Horovod 将尝试为所有检测到的框架构建扩展。有关可在构建 Horovod 之前设置的其他环境变量的详细信息,请参阅环境变量文档。

创建新环境后,您可以使用以下命令激活该环境。

$ conda activate $ENV_PREFIX

postBuild 文件

如果你想使用environment.ymlrequirements.txt文件中包含的任何JupyterLab扩展,那么你可能需要重新构建JupyterLab应用程序。

为简化操作,我们通常将重新构建JupyterLab的说明包含在 postBuild 脚本中。以下是示例Horovod环境中该脚本的内容。

jupyter labextension install --no-build jupyterlab-nvdashboard
jupyter labextension install --no-build jupyterlab_tensorboard
jupyter lab build

使用以下命令来执行 postBuild 脚本。

$ conda activate $ENV_PREFIX # optional if environment already active
$ . postBuild

列出Conda环境的内容

要查看环境中安装的所有软件包完整列表,请运行以下命令。

$ conda activate $ENV_PREFIX # optional if environment already active
$ conda list

验证Conda环境

构建完 Conda 环境后,使用以下命令检查 Horovod 是否已构建支持深度学习框架 TensorFlow、PyTorch、Apache MXNet,以及控制器 MPI 和 Gloo。

$ conda activate $ENV_PREFIX # optional if environment already active
$ horovodrun --check-build

您应该会看到类似以下的输出:

Horovod v0.19.4:
Available Frameworks:
    [X] TensorFlow
    [X] PyTorch
    [X] MXNet
Available Controllers:
    [X] MPI
    [X] Gloo
Available Tensor Operations:
    [X] NCCL
    [ ] DDL
    [ ] CCL
    [X] MPI
    [X] Gloo

将所有内容封装在Bash脚本中

我们通常将这些命令封装到一个shell脚本create-conda-env.sh中。运行该shell 脚本将设置Horovod构建变量,创建Conda环境,激活Conda 环境,并使用任何额外的扩展构建JupyterLab。

#!/bin/bash --login

set -e

export ENV_PREFIX=$PWD/env
export HOROVOD_CUDA_HOME=$CUDA_HOME
export HOROVOD_NCCL_HOME=$ENV_PREFIX
export HOROVOD_GPU_OPERATIONS=NCCL
conda env create --prefix $ENV_PREFIX --file environment.yml --force
conda activate $ENV_PREFIX
. postBuild

我们建议您将脚本放在项目根目录下的bin目录中。从项目根目录按如下方式运行脚本。

./bin/create-conda-env.sh # assumes that $CUDA_HOME is set properly

更新Conda环境

如果在环境已经创建后向 environment.yml 文件或 requirements.txt 文件添加(移除)依赖项,那么你可以使用以下命令重新创建环境。

$ conda env create --prefix $ENV_PREFIX --file environment.yml --force

然而,每当我们添加(移除)依赖项时,我们更倾向于重新运行Bash脚本,该脚本将重新构建Conda环境和JupyterLab。

$ ./bin/create-conda-env.sh