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. 修复后的验收顺序:从底层逐级往上,别直接满负载
- PCIe 设备完整:
lspci -Dnn -d 10de:22a3应见 4 颗(其他平台以实际拓扑与 OEM 文档为准); - 设备节点完整:
ls -l /dev/nvidia-nvswitch{0..3}; - FM 正常:
systemctl is-active nvidia-fabricmanager为active,日志不再出现拓扑数量不匹配; - Fabric 注册完成:
nvidia-smi -q | grep -A4 -i Fabric,8 卡均Completed / Success; - CUDA 可初始化:
cuInit(0)返回 0; - 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 板、主板之间的线缆、供电、复位和固件链路。
三条经验:
- 先控制面、后数据面——
cuInit不过,一切 NCCL 参数调整都是无用功; - 设备数量是第一类证据——"拓扑要求 4 颗、实见 3 颗"这种计数不匹配,比任何日志措辞都直接;
- 验收按枚举→节点→FM→Fabric→CUDA→NCCL 逐级推进——跳级的"恢复"无法定位回归发生在哪一层。
系列目录
- KV Cache 与前缀缓存:从原理到 99.9% 命中率的生产实践
- PD 分离实战:Prefill/Decode 拆池、配比拐点与容量规划
- GPU→内存→SSD 三级 KV 缓存:Mooncake 分层实战与跨引擎复用陷阱
- Kimi-K3 原始 MXFP4 权重512K 长上下文生产部署:双机 16 卡 TP8×PP2 与 CUDA Graph 调优
- 大模型压测方法论:如何让性能数据可信
- 推理集群可观测性:64 卡监控体系与缓存证据链
- MiniMax-H3视频生成服务化:ComfyUI 多 GPU 编排与长任务生命周期
- 掉卡排查实录:RTX 5070 反复 Xid 79,如何排查建立证据链
- GPU对调定位法:8 卡 RTX 6000D 掉卡,如何用对调缩小故障范围
- CUDA 802 不是 NCCL 网络故障:H20 NVSwitch 物理链路排查实录(本篇)
- DeepSeek-V4.1-Flash 双机 16 卡 H20 部署压测:TP8×DP2 与跨机 EP 的边界
数据声明:本文为单节点(n=1)故障与现场恢复反馈的排查实录;NCCL 报错、FM 日志与 PCIe 枚举信息均来自现场记录,容器名以
<container>占位,缺失设备的 BDF 推断为本节点现场映射,不应推广到其他 H20 服务器。