多实例 GPU (MIG)#

多实例 GPU 是一项技术,允许将单个 GPU 划分为多个实例,使每个实例看起来像一个完全独立的 GPU。然后,每个实例获得 GPU 计算资源的特定切片以及预定义的一块内存,这块内存通过片上保护与其余实例隔离。

由于保护层使 MIG 安全,存在某些限制。对于 HPC 应用来说,一个通常很重要的限制是不支持 CUDA 进程间通信 (IPC),IPC 允许通过 NVLink 和 NVSwitch 进行传输,从而极大地加速物理 GPU 之间的通信。因此,在使用 MIG 时,NVLink 和 NVSwitch 完全不可用,迫使应用程序必须通过系统(CPU)内存使用更昂贵的通信通道。

考虑到通信能力的限制,我们建议用户在尝试设置 MIG 实例集群时,首先理解必须做出的权衡。虽然分区可能对某些只需要一定计算能力的应用有益,但通信瓶颈可能是一个问题,因此需要仔细考虑。

Dask 集群#

只要所有 MIG 实例在内存方面是相同的,Dask-CUDA 就支持由 MIG 实例组成的 Dask 集群。就像物理 GPU 集群一样,混合不同内存大小的 GPU 通常不是一个好主意,因为 Dask 可能无法正确平衡工作负载,最终可能导致更频繁的内存不足错误。

例如,将两个 GPU 各划分为 7 个 10GB 实例,并使用全部 14 个实例构建集群是可以的。但是,应避免将一个 GPU 划分为 7 个 10GB 实例,而将另一个划分为 3 个 20GB 实例。

与由未分区 GPU 组成的系统不同,Dask-CUDA 无法自动推断集群将使用的 GPU。在 MIG 设置中,用户需要指定集群使用的 GPU 实例。这可以通过为 dask_cuda.LocalCUDAClusterdask-cuda-worker 指定 CUDA_VISIBLE_DEVICES 环境变量,或为 dask_cuda.LocalCUDACluster 指定同名参数来实现。

物理 GPU 可以通过其索引 [0..N)(其中 N 是安装的 GPU 总数)或通过由 GPU- 前缀后跟其 UUID 组成的名称来寻址。MIG 实例没有索引,只能通过其名称来寻址,名称由 MIG- 前缀后跟其 UUID 组成。MIG 实例的名称类似于:MIG-41b3359c-e721-56e5-8009-12e5797ed514

确定 MIG 名称#

确定 MIG 实例名称的最简单方法是在命令行上运行 nvidia-smi -L

$ nvidia-smi -L
GPU 0: NVIDIA A100-PCIE-40GB (UUID: GPU-84fd49f2-48ad-50e8-9f2e-3bf0dfd47ccb)
  MIG 2g.10gb     Device  0: (UUID: MIG-41b3359c-e721-56e5-8009-12e5797ed514)
  MIG 2g.10gb     Device  1: (UUID: MIG-65b79fff-6d3c-5490-a288-b31ec705f310)
  MIG 2g.10gb     Device  2: (UUID: MIG-c6e2bae8-46d4-5a7e-9a68-c6cf1f680ba0)

在上面的示例中,系统有一个 NVIDIA A100,包含 3 个 10GB MIG 实例。在接下来的章节中,我们将看到如何使用实例名称启动由 MIG GPU 组成的 Dask 集群。请注意,一旦 GPU 被分区,物理 GPU(上例中名为 GPU-84fd49f2-48ad-50e8-9f2e-3bf0dfd47ccb)将无法用于 CUDA 计算,也不能用作 Dask 集群的一部分。

或者,可以使用 NVMLPyNVML 通过编程方式获取 MIG 实例名称。请参阅 NVML API 来编写适用于此目的的实用程序。

LocalCUDACluster#

假设您在本地系统上有 3 个 MIG 实例

  • MIG-41b3359c-e721-56e5-8009-12e5797ed514

  • MIG-65b79fff-6d3c-5490-a288-b31ec705f310

  • MIG-c6e2bae8-46d4-5a7e-9a68-c6cf1f680ba0

要启动 dask_cuda.LocalCUDACluster,用户将运行以下命令

from dask_cuda import LocalCUDACluster

cluster = LocalCUDACluster(
    CUDA_VISIBLE_DEVICES=[
        "MIG-41b3359c-e721-56e5-8009-12e5797ed514",
        "MIG-65b79fff-6d3c-5490-a288-b31ec705f310",
        "MIG-c6e2bae8-46d4-5a7e-9a68-c6cf1f680ba0",
    ],
    # Other `LocalCUDACluster` arguments
)

dask-cuda-worker#

假设您在本地系统上有 3 个 MIG 实例

  • MIG-41b3359c-e721-56e5-8009-12e5797ed514

  • MIG-65b79fff-6d3c-5490-a288-b31ec705f310

  • MIG-c6e2bae8-46d4-5a7e-9a68-c6cf1f680ba0

要启动一个 dask-cuda-worker,其调度器地址位于 scheduler.json 文件中,用户将运行以下命令

CUDA_VISIBLE_DEVICES="MIG-41b3359c-e721-56e5-8009-12e5797ed514,MIG-65b79fff-6d3c-5490-a288-b31ec705f310,MIG-c6e2bae8-46d4-5a7e-9a68-c6cf1f680ba0" dask-cuda-worker scheduler.json # --other-arguments

请注意,在上面的示例中,我们在一个节点上创建了 3 个 Dask-CUDA worker;对于多节点集群,需要指定正确的 MIG 名称,并且它们在每个主机上总是不同的。

使用 Dask 集群的 XGBoost#

目前 XGBoost 只通过 NCCL 支持 GPU 通信,而 NCCL 不支持 MIG。因此,使用 XGBoost 的 Dask 集群必须转而使用 TCP 进行所有通信,这很可能导致性能显著下降。因此,不建议将 XGBoost 与 MIG 一起使用。