CUDA 802 不是 NCCL 网络故障:H20 NVSwitch 物理链路排查实录

CUDA 802 不是 NCCL 网络故障:H20 NVSwitch 物理链路排查实录

Deng YongJie's blog 5 2026-10-06

CUDA 802 不是 NCCL 网络故障:H20 NVSwitch 物理链路排查实录

大模型推理基础设施实战系列 · 第 10 篇

前两篇的 Xid 79 都是"卡从总线上消失";本篇换一种消失法:NVSwitch 从总线上消失。它最有教训价值的地方是——报错由 NCCL/MPI 测试暴露,但现场处置指向 NVSwitch 的物理连接路径。这是三篇中有现场恢复反馈的案例,因此也能给出从定位到验收的完整链路。

1. 背景与问题:8 个 MPI 进程同时报"system not yet initialized"

故障节点:8 张 NVIDIA H20 + 8 张 400G ConnectX-7 计算网卡(另有两个已关闭、不参与业务的 mlx5 网口)。执行 NCCL all_reduce_perf 时,8 个 MPI 进程几乎同时失败:

localhost: Test CUDA failure common.cu:894 'system not yet initialized'
 .. localhost pid 993: Test failure common.cu:844
...
mpirun detected that one or more processes exited with non-zero status
Exit code: 2

现场还伴随 OpenFabrics 和 mlx5 告警,第一反应很容易落在网卡、GID、MPI BTL 或 NCCL 参数上。但关键短语是 Test CUDA failure:如果 CUDA 初始化本身失败,NCCL 根本没有机会进入拓扑探测、通信路径选择或集合通信阶段。

两个读报错的常识先放在这:

  • 8 个 rank 报 8 次,是因为每个 rank 都要初始化 CUDA——它们在同一系统状态下启动,得到相同错误各打印一次;common.cu:894 只是当前 nccl-tests 构建版本上报 CUDA API 错误的位置,不代表该文件有缺陷;
  • 被 MPI 点名为"第一个非零退出进程"的 rank,不代表对应 GPU 是坏卡;任一 rank 退出后 mpirun 按默认策略终止整个作业——最后几段 MPI 输出是后果,不是根因。

2. 结论先行

这不是 NCCL、Open MPI、Docker 或 RoCE 选路故障。宿主机直接执行 cuInit(0) 就返回 802,说明 CUDA 在通信库介入前就没有完成初始化。

本例中,Fabric Manager 的拓扑要求 4 颗 NVSwitch,实际只发现 Physical ID 0、1、3——Physical ID 2 未出现在 PCIe 总线上,导致 GPU 无法完成 NVLink Fabric 注册。

故障随后逐层上传:FM 退出 → 8 张 GPU 的 Fabric 状态停在 In Progress / N/A → CUDA 返回 CUDA_ERROR_SYSTEM_NOT_READY → nccl-tests 与 MPI 打印错误并终止作业。

最终恢复手段:断电后重新插拔 GPU 基板—SW 板—主板之间的连接线。重新上电后第 4 颗 NVSwitch 恢复枚举,整条软件栈随之恢复正常。

故障因果链与恢复门槛

3. 最小化复现:先绕过 NCCL、MPI 和 RDMA

排查这类问题最有效的方法不是继续叠加 NCCL 参数,而是先验证宿主机能否初始化 CUDA Driver API:

python3 -c \
'import ctypes; print("cuInit rc =", ctypes.CDLL("libcuda.so.1").cuInit(0))'

现场结果:cuInit rc = 802。错误码 802 对应 CUDA_ERROR_SYSTEM_NOT_READY——系统尚未准备好启动 CUDA 工作(CUDA Driver API 错误码)。

这一步把故障范围缩小为宿主机 CUDA 初始化失败:已足够把首轮排查重点移到平台初始化;它本身不是所有软件与硬件路径的排除证明。严格地说,nccl-tests 不一定在源码里显式调用同一个 cuInit(0)——它在设备枚举和初始化阶段调用 CUDA API,从而触发底层驱动初始化。

再做一层排除:单容器、单 GPU、关掉 IB 与 NVLS——

docker exec \
  -e CUDA_VISIBLE_DEVICES=0 \
  -e 'OMPI_MCA_btl=^openib' \
  -e NCCL_IB_DISABLE=1 \
  -e NCCL_NVLS_ENABLE=0 \
  -e NCCL_DEBUG=INFO \
  <container> \
  /root/nccl-tests/build/all_reduce_perf -b 1M -e 1M -f 2 -g 1

测试仍停在 # Using devices 之后,报同样的 system not yet initialized。这说明多进程规模及 NCCL 的 IB/NVLS 选择不是重现该错误的必要条件;系统级 Fabric 拓扑仍未就绪,不能说“多卡拓扑已排除”。

4. 决定性线索:Fabric Manager 数不对 NVSwitch

检查 Fabric Manager(FM),服务持续启动失败,核心日志:

detected number of NVSwitches don't match with any supported system topology,
aborting fabric manager

同时记录:

number of devices specified in topology file NVSwitches: 4, GPUs: 8

Physical Id: 0  PCI Bus ID: 00000000:03:00.0
Physical Id: 1  PCI Bus ID: 00000000:04:00.0
Physical Id: 3  PCI Bus ID: 00000000:06:00.0

拓扑文件成功解析,要求 8 GPU + 4 NVSwitch;实际只检测到 Physical ID 0、1、3,Physical ID 2 缺失。

HGX H20 使用第三代 NVSwitch,除非另有说明,其操作步骤与 HGX H100 相同(8 GPU + 4 NVSwitch 基板)——见 Fabric Manager 支持平台与 HGX H100 基板拓扑。

5. PCIe 与设备节点完成证据闭环

lspci -Dnn -d 10de:22a3

现场只看到 3 个 NVSwitch(10de:22a3 为 GH100 NVSwitch 的 PCI ID):

0000:03:00.0 Bridge: NVIDIA Corporation GH100 NVSwitch [10de:22a3]
0000:04:00.0 Bridge: NVIDIA Corporation GH100 NVSwitch [10de:22a3]
0000:06:00.0 Bridge: NVIDIA Corporation GH100 NVSwitch [10de:22a3]

结合 Physical ID 与本节点连续的 BDF 布局,可推断缺失位置为 0000:05:00.0——这是本节点的现场映射,不应推广成所有 H20 服务器的固定 BDF。

设备节点也只有 3 个:/dev/nvidia-nvswitch0、1、2(另有 nvidia-nvswitchctl)。注意 nvidia-nvswitch2 是第三个被驱动发现的设备,并不等于 Physical ID 2——FM 日志表明它实际对应 Physical ID 3。

关键推论:内核只 probe 了 03:00.0、04:00.0、06:00.0,没有 05:00.0 的 probe 记录——问题发生在驱动绑定之前:操作系统 PCIe 层根本没有枚举到该设备。

6. 为什么 CUDA 会返回 802:Fabric 注册是前置条件

8 张 GPU 的 nvidia-smi -q 均显示:

Fabric
    State  : In Progress
    Status : N/A

按 NVIDIA 官方说明,Hopper NVSwitch 系统上的 GPU 需要完成向 NVLink Fabric 的注册,CUDA 初始化才会继续;

注册中显示 In Progress / N/A,成功后应为 Completed / Success(初始化 NVSwitch 和 NVLink)。

官方还明确指出:H100 类系统如果 NVLink Switch 不可用,GPU 将无法完成 Fabric 注册,CUDA 应用启动会失败,H20 默认遵循同类步骤(H100 NVSwitch 故障行为)。

所以更准确的因果关系不是"FM 没运行所以 CUDA 失败",而是:NVSwitch 不可用导致 Fabric 注册无法完成;FM 的拓扑检查也因同一底层问题而退出。 两者是同一根因的两个表现。

完整证据链:

层级 现场证据 得出的结论
PCIe 只有 3 个 10de:22a3 第 4 颗 NVSwitch 未被枚举
驱动设备节点 只有 3 个 NVSwitch 字符设备 驱动没有可绑定的第 4 个设备
Fabric Manager 拓扑要求 4 颗,实见 3 颗后退出 平台拓扑校验失败
GPU Fabric 8 张卡均 In Progress / N/A Fabric 注册未完成
CUDA Driver 宿主机 cuInit(0) 返回 802 CUDA 系统尚未就绪
nccl-tests common.cu 报 CUDA failure 测试程序向上传递 CUDA 错误
MPI rank 退出码 2,作业被终止 MPI 只是清理失败作业

同时核实:FM、已加载驱动、内核模块版本均为 535.247.01——最常见的驱动与 FM 版本不匹配被排除,但这不等于排除了所有固件或硬件路径问题。

7. 为什么禁用 IB / P2P / NVLS 都无效

要把平台初始化和 NCCL 通信选择分成两个阶段看:

两个阶段与分层排查顺序

三个常用开关各自的作用域(NCCL 环境变量):

  • NCCL_IB_DISABLE=1:只禁止 NCCL 使用 IB/RoCE,回退其他传输;
  • NCCL_P2P_DISABLE=1:关闭 NCCL 的 P2P transport;
  • NCCL_NVLS_ENABLE=0:控制 NVLink SHARP 的使用。

这些参数都不能让一颗未被 PCIe 枚举的 NVSwitch 重新出现,也不能替代 Fabric 注册。 CUDA_VISIBLE_DEVICES=0 只限制进程可见的 GPU,同样绕不开系统级 Fabric 就绪条件。cuInit(0)=802 时继续排列组合 NCCL 参数,是在第二阶段的工具里找第一阶段的问题。

8. 根因与修复:一次断电重插

据现场维护反馈,本机 NVSwitch 的主机侧通信与 PCIe 枚举,依赖一条贯穿 GPU 基板 → SW 板 → 主板 的物理连接链路;该链路的线缆存在接触/连接异常,导致 Physical ID 2 无法被主板枚举。项目现场记录将根因定位为这条物理连接链路。下述修复结果保留该历史结论;本轮文档审校没有重新执行硬件验收。

维护反馈称,人员按 OEM 流程将服务器完全断电,重新插拔该连接线后重新上电:第 4 颗 NVSwitch 重新出现在 PCIe 总线上,FM 正常启动,8 张 GPU 完成 Fabric 注册,cuInit(0) 返回 0,NCCL 测试恢复。

线缆重插不是在线热插拔:必须在维护窗口内完全断电,遵循厂商的防静电、线缆方向、接口锁止与上电检查流程。完整断电不是 reboot,也不是只重启 BMC。

同类故障的处置顺序:先保存现场证据,再进维护窗口。建议至少收集:

nvidia-bug-report.sh
journalctl -u nvidia-fabricmanager -b --no-pager
journalctl -k -b --no-pager
lspci -Dtv
lspci -Dnn -d 10de:22a3
ipmitool sel elist

如果完整断电后设备仍未枚举,提交硬件支持,排查方向包括 NVSwitch 本体、GPU Baseboard 供电与复位、上游 PCIe bridge/retimer、link training、CPLD/HMC/ERoT、BIOS 与基板固件。仅凭操作系统日志不能直接断言 NVSwitch ASIC 损坏——能精确定位的是"Physical ID 2 所在 PCIe 枚举链路失败",部件定责需要 BMC/AHS/SEL、固件清单和厂商诊断。

9. 修复后的验收顺序:从底层逐级往上,别直接满负载

  1. PCIe 设备完整:lspci -Dnn -d 10de:22a3 应见 4 颗(其他平台以实际拓扑与 OEM 文档为准);
  2. 设备节点完整:ls -l /dev/nvidia-nvswitch{0..3};
  3. FM 正常:systemctl is-active nvidia-fabricmanager 为 active,日志不再出现拓扑数量不匹配;
  4. Fabric 注册完成:nvidia-smi -q | grep -A4 -i Fabric,8 卡均 Completed / Success;
  5. CUDA 可初始化:cuInit(0) 返回 0;
  6. NCCL 逐步恢复:先单卡禁 IB(-g 1),再单进程 8 卡(-b 8M -e 12G -f 2 -g 8),通过后再依次引入 MPI、多节点和 IB/RoCE——每一步只增加一个变量。

10. 效果与总结

现场恢复反馈与故障前日志相符,但本文没有附逐项修复后原始输出;下节清单是验收要求,不能冒充每项均有独立复核记录。

本次故障最有价值的经验:不要把"由 NCCL 测试暴露的错误"直接等同于"NCCL 故障"。 第 4 颗 NVSwitch 未被 PCIe 枚举 → Fabric 注册无法完成 → FM 因拓扑数量不匹配退出 → CUDA 802 → nccl-tests 打印 system not yet initialized → MPI 终止所有 rank——一条自下而上的因果链,最末一环才是用户看到的报错。

最短定位路径:

宿主机 cuInit → GPU Fabric 状态 → Fabric Manager 日志 → lspci 与设备节点

当这四层证据能相互印证时,就可以停止在 Docker、NCCL 和 mlx5 参数中兜圈子,把重心转向 NVSwitch 的 PCIe 枚举,以及基板、SW 板、主板之间的线缆、供电、复位和固件链路。

三条经验:

  1. 先控制面、后数据面——cuInit 不过,一切 NCCL 参数调整都是无用功;
  2. 设备数量是第一类证据——"拓扑要求 4 颗、实见 3 颗"这种计数不匹配,比任何日志措辞都直接;
  3. 验收按枚举→节点→FM→Fabric→CUDA→NCCL 逐级推进——跳级的"恢复"无法定位回归发生在哪一层。

系列目录

  1. KV Cache 与前缀缓存:从原理到 99.9% 命中率的生产实践
  2. PD 分离实战:Prefill/Decode 拆池、配比拐点与容量规划
  3. GPU→内存→SSD 三级 KV 缓存:Mooncake 分层实战与跨引擎复用陷阱
  4. Kimi-K3 原始 MXFP4 权重512K 长上下文生产部署:双机 16 卡 TP8×PP2 与 CUDA Graph 调优
  5. 大模型压测方法论:如何让性能数据可信
  6. 推理集群可观测性:64 卡监控体系与缓存证据链
  7. MiniMax-H3视频生成服务化:ComfyUI 多 GPU 编排与长任务生命周期
  8. 掉卡排查实录:RTX 5070 反复 Xid 79,如何排查建立证据链
  9. GPU对调定位法:8 卡 RTX 6000D 掉卡,如何用对调缩小故障范围
  10. CUDA 802 不是 NCCL 网络故障:H20 NVSwitch 物理链路排查实录(本篇)
  11. DeepSeek-V4.1-Flash 双机 16 卡 H20 部署压测:TP8×DP2 与跨机 EP 的边界

数据声明:本文为单节点(n=1)故障与现场恢复反馈的排查实录;NCCL 报错、FM 日志与 PCIe 枚举信息均来自现场记录,容器名以 <container> 占位,缺失设备的 BDF 推断为本节点现场映射,不应推广到其他 H20 服务器。