GPU 软件

在多 GPU 服务器上运行 NCCL 测试:all_reduce_perf 分步指南

在开始长时间训练之前,请先确认全部 8 张 GPU 之间能以全速通信。这些检查耗时很短,能及早发现大多数互联问题。

本页内容
  1. 检查 GPU 拓扑
  2. 编译 nccl-tests
  3. 在 8 张 GPU 上运行 all_reduce_perf
  4. busbw 的含义
  5. 用 NCCL_DEBUG=INFO 调试
  6. 用 torchrun 启动 DDP 或 FSDP 任务
  7. 多节点注意事项

在多 GPU 服务器上运行 NCCL 测试,是在投入长时间训练之前,确认 GPU、NVLink 和通信栈能够协同工作的最快方法。本页适用于我们的 8 卡服务器:检查拓扑,编译 NVIDIA 的 nccl-tests,在 8 张 GPU 上运行 all_reduce_perf,读懂 busbw,然后用 torchrun 启动 PyTorch 任务。多节点注意事项放在最后。AMD 服务器使用 RCCL,详见 ROCm 配置。

检查 GPU 拓扑

nvidia-smi topo -m
nvidia-smi nvlink --status
systemctl status nvidia-fabricmanager

在 topo -m 矩阵中,NV# 表示两张 GPU 通过 NVLink 相连,其中 # 为链路数量。PIX、PXB、PHB、NODE 和 SYS 都是 PCIe 路径,按距离由近到远排列。该矩阵还会显示每张 GPU 的 CPU 亲和性和 NUMA 亲和性。

在 HGX 服务器(H100、H200、B200、B300)上,每一对 GPU 之间都应显示 NV 条目,并且 Fabric Manager 应处于 active (running) 状态。RTX PRO 6000 服务器没有 NVLink:其 GPU 之间通过 PCIe 通信,因此在这台服务器上出现 PCIe 条目属于正常现象。背景知识请参阅 NVLink 与 PCIe 对比。

编译 nccl-tests

  1. 安装编译工具,并检查是否存在 NCCL 开发头文件:
    sudo apt install -y git build-essential
    ls /usr/include/nccl.h
  2. 如果缺少 nccl.h,请从 NVIDIA 的 CUDA 软件源安装 NCCL,该软件源的配置方法见驱动与 CUDA 版本。先列出可用版本,然后选择 CUDA 后缀(例如 +cuda12.8)不高于 nvidia-smi 所显示“CUDA Version”的最新版本:
    apt-cache madison libnccl2 | head
    sudo apt install -y libnccl2=VERSION libnccl-dev=VERSION
  3. 编译测试程序:
    git clone https://github.com/NVIDIA/nccl-tests.git
    cd nccl-tests
    make -j"$(nproc)" CUDA_HOME=/usr/local/cuda
    生成的二进制文件位于 ./build/ 中。

如果不想改动主机环境,可以在 NGC PyTorch 容器内用同样的方法编译,该容器已包含 CUDA 和 NCCL。

在 8 张 GPU 上运行 all_reduce_perf

./build/all_reduce_perf -b 8 -e 8G -f 2 -g 8

由一个进程驱动 8 张 GPU(-g 8),数据量从 8 字节(-b)增加到 8 GB(-e),每一步翻倍(-f 2)。每一行都会针对 out-of-place 和 in-place 两种运行方式,分别给出耗时以及 algbw 和 busbw 两个带宽数值。请确认:

  • 每一行的 #wrong 列都为 0,说明结果正确;
  • busbw 随消息大小增加而上升,并在最大的几档消息大小处趋于平稳;
  • 最后的“Avg bus bandwidth”一行在多次运行之间保持稳定。

其他集合通信操作的测试用法相同:all_gather_perf、reduce_scatter_perf 和 sendrecv_perf。

busbw 的含义

algbw 是数据量除以耗时。它会随 GPU 数量变化,因此很难在不同配置之间比较。busbw 乘上了一个修正系数,使该数值能反映每条链路实际承载的流量。对于 all-reduce,该系数为 2 × (n − 1) / n,8 张 GPU 时为 1.75。这样,busbw 就可以与硬件的链路带宽比较,也可以在同型号的服务器之间比较。

厂商标称的链路速度是测试达不到的峰值,因此应以结果的一致性作为判断依据:比较多次运行的结果;如果您有一台配置相同的服务器,也与它比较。大消息时带宽骤降、结果远低于同型号的另一台服务器,或者测试卡住不动,通常说明拓扑、Fabric Manager 或硬件存在问题。请通过控制台中的工单,把完整输出和拓扑矩阵发给我们。

用 NCCL_DEBUG=INFO 调试

NCCL_DEBUG=INFO ./build/all_reduce_perf -b 1G -e 1G -g 8 2>&1 \
  | tee nccl-debug.log

日志会显示 NCCL 版本、GPU 之间选用的传输方式(经 NVLink 的 P2P 或 NVLS、经主机内存的 SHM、经网络的 NET),以及 NCCL 构建的环(ring)和树(tree)。在 HGX 服务器上,您应该看到 NVLink 传输方式。如果看到的是 SHM,请检查拓扑和 Fabric Manager。在基于 PCIe 的 RTX PRO 6000 服务器上,如果测试卡住或报错,请加上 NCCL_P2P_DISABLE=1 重新运行。如果这次运行正常,问题就出在点对点(P2P)通信上:请在控制台提交工单,我们可以协助排查。

用 torchrun 启动 DDP 或 FSDP 任务

torchrun 会为每张 GPU 启动一个进程,并设置 PyTorch 分布式包所需的环境变量。在装有 PyTorch 的环境中,将以下检查脚本保存为 allreduce_check.py:

import os
import torch
import torch.distributed as dist

dist.init_process_group("nccl")
rank = int(os.environ["LOCAL_RANK"])
torch.cuda.set_device(rank)
x = torch.ones(1024, device="cuda") * (rank + 1)
dist.all_reduce(x)
print(f"rank {rank}: {x[0].item()}")
dist.destroy_process_group()

在全部 8 张 GPU 上运行它:

torchrun --standalone --nproc_per_node=8 allreduce_check.py

每个 rank 都应输出 36.0,即 1 到 8 之和。您的 DDP 或 FSDP 训练脚本也以同样的方式启动。DDP 在每张 GPU 上保留一份完整的模型副本,并对梯度求平均。FSDP 将参数、梯度和优化器状态分片到各张 GPU 上,因此可以训练单张 GPU 显存装不下的模型。任务卡住时,在命令前加上 NCCL_DEBUG=INFO。

多节点注意事项

  • 网络。申请在您的服务器之间开通私有网络(在部署服务器时写在订单备注中,或在控制台提交工单),并让 rendezvous 和 NCCL 流量使用私有地址。
  • 网络接口。用 ip -br addr 找到私有网络接口,并在每个节点上将 NCCL_SOCKET_IFNAME 设置为该接口的名称,以免 NCCL 选中公网接口。
  • 启动。在每个节点上运行同一条命令,只修改 rank。此处的 10.0.0.1 代表第一个节点的私有地址:
    torchrun --nnodes=2 --nproc_per_node=8 --node_rank=0 \
      --master_addr=10.0.0.1 --master_port=29500 train.py
    在第二个节点上使用 --node_rank=1;如果启用了防火墙,请在节点之间放行该端口。
  • 高速互联。节点之间要以全速传输 GPU 流量,需要在您的服务器之间布线并配置 RDMA 网络(InfiniBand 或 RoCE),而私有网络并不提供这一能力。如果单个任务需要超过 8 张 GPU 以 NVLink 速度交换数据,GB300 NVL72 机架可以把全部 72 张 GPU 置于同一个 NVLink 域中。

问题仍未解决?

请在控制台提交工单,写明服务器、您运行了什么以及错误输出(如有)。工程师 7×24 小时答复。

提交工单

登录 FullGPU

管理您的 GPU 服务器、余额和账单。

首次使用 FullGPU? 创建账户