新品 NVIDIA B300 · 288 GB HBM3e 服务器 — 起价 $4,019/月 每块 GPU

查看 B300

文档 · 多 GPU

单台服务器上的多 GPU:拓扑、NCCL 与 torchrun

服务器内 GPU 的连接方式决定了任务的扩展效果。在长时间运行任务之前,先检查拓扑、用 torchrun 启动,并测量互联性能。

更新于 5 分钟阅读

先查看拓扑

GPU 之间的连接方式决定了哪种并行方式成本更低。选择之前先看一看:

nvidia-smi topo -m        # GPU、网卡与 CPU 之间的连接矩阵
nvidia-smi topo -p2p r    # 哪些 GPU 对支持点对点读取
amd-smi topology          # 适用于 AMD MI355X
标识两块 GPU 之间的路径
NV#NVLink,# 表示绑定的链路数;在 HGX 板上通过 NVSwitch 连接
PIX最多经过一个 PCIe 交换芯片
PXB经过多个 PCIe 交换芯片,但不跨越 CPU 主桥
PHB经过一个 PCIe 主桥,通常意味着要经过 CPU
NODEPCIe 加上同一 NUMA 节点内主桥之间的互联
SYSPCIe 加上 CPU 插槽之间的链路:最慢的路径

CPU Affinity 和 NUMA Affinity 列显示了哪些核心离每块 GPU 最近。当 CPU 侧成为瓶颈时,把数据加载工作绑定到这些核心上。

用 torchrun 启动 2、4 或 8 GPU 任务

torchrun 会为每块 GPU 启动一个进程,并为每个进程分配 RANK、LOCAL_RANK 和 WORLD_SIZE。在开始长时间任务之前,先用一个简短脚本测试配置:

# ddp_check.py
import os
import torch
import torch.distributed as dist

local_rank = int(os.environ["LOCAL_RANK"])
torch.cuda.set_device(local_rank)
dist.init_process_group("nccl")

x = torch.ones(1, device="cuda") * dist.get_rank()
dist.all_reduce(x)          # 对所有 GPU 上的 rank 编号求和
print(f"rank {dist.get_rank()} of {dist.get_world_size()}: sum = {x.item():.0f}")
dist.destroy_process_group()
torchrun --standalone --nproc-per-node=gpu ddp_check.py   # 每个可见 GPU 一个进程
torchrun --standalone --nproc-per-node=4 train.py         # 四个进程
CUDA_VISIBLE_DEVICES=4,5,6,7 torchrun --standalone --nproc-per-node=4 train.py   # 仅使用 4 到 7 号 GPU

每个 rank 都应打印出相同的总和 0 + 1 + … + (n − 1):8 块 GPU 上的结果是 28。CUDA_VISIBLE_DEVICES 可以让两个独立任务共享一台服务器,各自使用自己的 GPU。torchrun 会为每个进程设置 OMP_NUM_THREADS=1,除非您自己另行设置;如果训练进程内的 CPU 工作较慢,可以调高这个值。

NCCL 要点

NCCL 是 PyTorch 的 nccl 后端背后所用的库。它会自动检测拓扑,并自行在 NVLink、PCIe 点对点、共享内存或网络之间做出选择,默认设置就能满足大多数任务。以下变量可以显示并调试它的选择结果:

变量用途
NCCL_DEBUG=INFO打印 NCCL 版本、检测到的拓扑,以及 GPU 之间使用的传输方式(例如 via P2P 或 via SHM 这类行)。日常运行请使用 WARN。
NCCL_DEBUG_SUBSYS=INIT,GRAPH将 INFO 输出限制为初始化和拓扑决策部分。
NCCL_DEBUG_FILE=/tmp/nccl.%h.%p.log将日志写入每个进程各自的文件(%h 为主机名,%p 为进程 ID)。
NCCL_P2P_DISABLE=1关闭 GPU 之间的直接传输。仅用于诊断挂起问题,不应作为常规设置保留。
NCCL_P2P_LEVEL=PXB只允许在给定距离内使用点对点传输:LOC、NVL、PIX、PXB、PHB 或 SYS。
NCCL_SHM_DISABLE=1关闭共享内存传输方式(仅用于调试)。
NCCL_TOPO_DUMP_FILE=/tmp/topo.xml保存 NCCL 检测到的拓扑。
NCCL_SOCKET_IFNAME、NCCL_IB_DISABLE网络相关设置,只有在任务跨多台服务器时才有意义。
NCCL_DEBUG=INFO torchrun --standalone --nproc-per-node=gpu ddp_check.py 2>&1 | grep -E 'via (P2P|SHM|NET)' | head

NCCL 的文档将 NCCL_ALGO、NCCL_PROTO 等调优变量列为调试辅助手段。不要把它们保留在生产脚本中,否则可能导致性能下降或程序挂起。

用 nccl-tests 测量总线带宽

nccl-tests 用于测量互联实际能提供的性能。它需要来自 NVIDIA 仓库的 CUDA 工具包和 NCCL 开发文件(参见 NVIDIA 驱动与 CUDA);NGC 的 PyTorch 容器已经自带这两者。

sudo apt install -y libnccl2 libnccl-dev
git clone https://github.com/NVIDIA/nccl-tests.git
cd nccl-tests
make -j                                          # CUDA_HOME 默认为 /usr/local/cuda
./build/all_reduce_perf -b 8 -e 2G -f 2 -g 8     # -g:服务器中的 GPU 数量

-b 和 -e 设置最小和最大的消息大小,-f 设置不同大小之间的倍数,-g 设置 GPU 数量。每一行输出对应一种消息大小:

  • algbw:数据大小除以耗时。
  • busbw:按 GPU 数量修正后的 algbw(对于 all-reduce,乘以 2(n − 1)/n)。它反映的是路径中最慢链路(NVLink、PCIe 或 CPU 插槽之间的链路)的速度,是在不同服务器之间进行比较的指标。
  • #wrong 必须始终为 0。运行结束时会输出一行 Avg bus bandwidth。

请关注大消息的行。在服务器状态正常时先记录一次结果,以便日后性能发生变化时可以对比。

更大的模型:FSDP 与 DeepSpeed

  • DDP(DistributedDataParallel):每块 GPU 都保存一份完整的模型和优化器状态副本。当一块 GPU 的显存足以容纳全部内容时,这种方式最简单也最快。
  • FSDP2(torch.distributed.fsdp.fully_shard):将参数、梯度和优化器状态分片到各个 GPU 上,因此模型只需要在所有 GPU 上合计放得下即可。启动方式与 DDP 一样使用 torchrun;参见 PyTorch 的 FSDP2 教程。
  • DeepSpeed ZeRO:第 1 到第 3 阶段依次对优化器状态、梯度、参数进行分片,并可选择将部分内容卸载到 CPU 内存或 NVMe。pip install deepspeed;参见入门指南。
  • 张量并行与流水线并行(例如 Megatron 风格):将各层或若干层拆分到不同 GPU 上。用于最大规模的模型;张量并行需要高速互联。

Hugging Face Accelerate 和 Transformers 的 Trainer 会把 DDP、FSDP 和 DeepSpeed 封装在一个配置文件之后。如果是做推理而不是训练,请参见推理服务。

AMD MI355X:RCCL

在 MI355X 上,同样的代码无需修改即可运行。PyTorch 的 nccl 后端使用的是 RCCL,也就是 AMD 对 NCCL API 的实现;torchrun 的用法完全相同,RCCL 读取的也是同样的 NCCL_* 变量,例如 NCCL_DEBUG=INFO。可以用 HIP_VISIBLE_DEVICES 选择 GPU;也支持 CUDA_VISIBLE_DEVICES。

amd-smi topology                           # GPU 之间的连接
git clone https://github.com/ROCm/rccl-tests.git
cd rccl-tests
make GPU_TARGETS=gfx950                    # 如果 ROCm 不在 /opt/rocm,请添加 HIP_HOME=...
./build/all_reduce_perf -b 8 -e 2G -f 2 -g 8

构建 rccl-tests 最简单的方式是使用 rocm/pytorch 容器,其中已经安装好了 ROCm 和 RCCL。安装步骤和 GPU 选择方式参见 MI355X 上的 ROCm。

对这篇指南有疑问?

请通过联系表单告诉我们您使用的 GPU、运行的命令以及得到的输出结果。

客户中心

登录 CryptGPU

您的订单、账单和服务器,一站式管理。

还没有 CryptGPU 账户?

账户是在结账时创建的:先选择您的服务器和软件,然后在首次下单的账户步骤中创建账户。

部署服务器