4. 任务中断类型:硬件故障、软件错误、网络问题、资源竞争等分类

分布式训练任务在千卡乃至万卡规模下运行时,中断并非“偶发事件”,而是需要被当作常态来管理的工程问题。要有效应对中断,第一步不是急着改代码或换硬件,而是建立一套清晰的中断分类学。只有准确归类,才能选择合适的恢复策略(如断点续训、弹性调度、自动重启)并确定排查优先级。本章将训练任务中断划分为四大类:硬件故障、软件错误、网络问题与资源竞争,并剖析每一类的典型特征、根因与判别线索。

4.1 硬件故障:不可忽视的“硬”中断

硬件故障是分布式训练中最“刚性”的中断来源——一旦发生,通常意味着物理组件失效,无法通过重试或参数调整绕过。在GPU集群中,故障点远不止GPU本身,而是覆盖整条数据与计算链路。

核心硬件故障域清单:

  • GPU 芯片与显存:ECC 错误(可纠正/不可纠正)、显存位翻转、GPU 卡死(Xid 错误,如 43、63、79、109 等)。
  • NVLink / PCIe 链路:链路降速、重训练(link retraining)、带宽抖动,导致集合通信超时。
  • CPU 与内存:CPU 过热降频、内存 ECC 报错、NUMA 访问延迟异常。
  • 存储子系统:本地 NVMe 盘损坏导致 checkpoint 写入失败;分布式文件系统(如 Lustre)节点故障。
  • 电源与散热:电源模块失效、GPU 温度过高触发热保护(通常伴随风扇全速运转)。

硬件故障的判别特征是“日志中常出现硬件专属错误码”,且故障往往在节点重启后依然存在(或间歇性复现)。例如,NVIDIA 驱动会向系统日志写入 Xid 错误,其中 Xid 79 表示 GPU 已从总线脱落,通常需要硬件更换;而 Xid 63 为 ECC 或显存错误,可能通过重置恢复,但若频繁出现则预示硬件寿命将尽。

# 典型硬件故障日志片段(dmesg / syslog)
[56701.234567] NVRM: Xid (PCI:0000:3b:00): 79, GPU has fallen off the bus.
[56701.234570] NVRM: Xid (PCI:0000:3b:00): 63, GPU0: ECC uncorrectable error detected.
[56702.102938] nvme0n1: I/O error, dev nvme0n1, sector 0x8a3f2c, op 0x1:(WRITE) flags 0x80000 phys_seg 0 prio class 0

在软件层面,硬件故障往往表现为进程突然退出且无 Python 堆栈,或 NCCL 初始化/通信时报“unexpected CUDA error”。此时应优先检查系统日志(dmesg、journalctl -k)而非应用日志。

分布式训练任务中断分类总览 🔧 硬件故障 GPU Xid / ECC NVLink / PCIe 链路 NVMe / 电源 / 散热 → 需硬件更换/隔离 🐞 软件错误 CUDA / 驱动版本不匹配 框架断言 / OOM 数据加载器异常 → 修复代码/环境 🌐 网络问题 NCCL 超时 / 通信失败 RDMA 丢包 / 拥塞 DNS / 路由异常 → 网络调优/重试 ⚡ 资源竞争 CPU 争抢 / 内存不足 PCIe 带宽争用 共享存储 IO 冲突 → 资源隔离/调度 任务中断表现 进程退出 · 挂起无响应 · 心跳丢失 · Checkpoint 失败 判别优先级 ① 查 dmesg 硬件错误 ② 查 NCCL 日志网络 ③ 查应用堆栈软件 ④ 查调度器资源竞争 四类中断并非互斥,实际故障可能叠加(如网络拥塞引发 NCCL 超时,进而触发 GPU 报错)

4.2 软件错误:可复现与不可复现的博弈

软件错误是另一大类中断来源,其特点是“进程有明确异常堆栈”,通常可通过日志定位到具体代码行。但分布式场景下,软件错误的表现形式比单机复杂得多——同一个错误可能只在特定 rank 上出现,也可能在迭代 N 次后才触发。

常见的软件错误可细分为以下子类:

子类 典型表现 示例
环境不一致 不同节点 CUDA/cuDNN 版本不同,或 Python 包版本漂移 Rank 0 使用 cuDNN 8.9,Rank 3 使用 8.6,导致卷积结果不一致
框架断言/崩溃 PyTorch 报 RuntimeError、AssertionError,或 NCCL 抛出 ncclSystemError 张量形状不匹配、all_gather 输出尺寸错误
显存溢出 (OOM) CUDA out of memory,但并非所有 rank 同时发生 某一 batch 的激活值特别大,或梯度检查点失效
数据加载异常 DataLoader worker 崩溃,或数据集文件缺失/损坏 TFRecord 文件被并发读取时句柄冲突
死锁/活锁 集合通信调用顺序不一致,导致部分 rank 等待 Rank 0 先 all_reduce 再 all_gather,Rank 1 反之

软件错误的排查核心在于“复现与对比”。如果错误可稳定复现,通常与代码逻辑或数据有关;如果错误随机出现,则需怀疑环境不一致或存在未定义行为(如多线程读写同一缓冲区)。

# 典型软件错误堆栈(PyTorch 分布式)
Traceback (most recent call last):
  File "train.py", line 245, in <module>
    loss.backward()
  File "/opt/conda/lib/python3.10/site-packages/torch/_tensor.py", line 492, in backward
    torch.autograd.backward(self, gradient, retain_graph, create_graph, inputs=inputs)
  File "/opt/conda/lib/python3.10/site-packages/torch/autograd/__init__.py", line 251, in backward
    Variable._execution_engine.run_backward(  # Calls into the C++ engine to run the backward pass
RuntimeError: NCCL error in: ProcessGroupNCCL.cpp:1260, unhandled system error, NCCL version 2.18.3
  last error: NCCL error: 2, unhandled system error

判别技巧:当 NCCL 报错时,先看错误码。NCCL 错误码 1 = 未初始化,2 = 系统错误,3 = 内部错误,4 = 非法参数,5 = 不支持操作,6 = 资源耗尽。错误码 2 往往与网络或硬件相关,而非纯软件问题。

4.3 网络问题:隐形的“慢性杀手”

网络问题在分布式训练中极具迷惑性——它不像硬件故障那样直接崩溃,而是表现为“训练变慢、间歇性超时、NCCL 通信挂起”。在千卡规模下,网络问题是最常见的中断诱因之一,且排查难度最高。

网络问题可归纳为三个层面:

  1. 物理链路层:光模块信号衰减、网线/光纤接触不良、交换机端口丢包。这类问题通常需要 ethtool -S 查看网卡丢包计数,或使用 ibstatus(InfiniBand)检查链路速率与状态。
  2. 协议与拥塞层:TCP 重传率升高、RDMA 拥塞控制失效、NCCL 使用的 IB 队列对(QP)超限。表现为 all_reduce 耗时从 10ms 飙升至 500ms。
  3. 拓扑与路由层:多轨网络(multi-rail)配置错误,或路由不对称导致部分节点间通信绕远。例如,本应通过 spine 交换机直连的两个节点,实际走了三层路由。

网络问题的典型日志特征是“NCCL 超时 + 心跳丢失”,但节点本身并未宕机。PyTorch 分布式默认的 timeout 参数为 30 分钟,若网络抖动导致集合通信超过该阈值,训练任务即被强制终止。

# NCCL 超时日志特征
[rank0]:[E ProcessGroupNCCL.cpp:1024] [Rank 0] Watchdog caught collective operation timeout: WATCHDOG TIMEOUT at rank 0 (ranks 0,3,5,7...)
[rank0]:[E ProcessGroupNCCL.cpp:1041] [Rank 0] Some NCCL operations have failed or timed out. Because of the asynchronous nature of NCCL, the failure can be caused by other ranks.

重要误区:不要一看到 NCCL 超时就判定为“网络故障”。NCCL 超时也可能是 GPU 卡死(硬件)、CPU 负载过高导致无法及时调用 NCCL(资源竞争)、或代码死锁(软件)的次生表现。正确做法是先检查网卡丢包与重传统计,再排查 GPU 状态。

4.4 资源竞争:被低估的“软性中断”

资源竞争是四类中断中最容易被忽视的一类,因为它不产生明确的错误日志,而是通过“性能劣化→超时→任务被杀”的间接路径导致中断。在共享 GPU 集群中,资源竞争尤为常见。

主要资源竞争场景包括:

  • CPU 争抢:数据加载(DataLoader)与 GPU 通信同时争抢 CPU 核心,导致 NCCL 调用延迟,触发 watchdog 超时。
  • 内存带宽竞争:多个容器共享同一 NUMA 节点,内存带宽被榨干,导致 GPU 无法及时获取数据。
  • PCIe 带宽争用:GPU 与 NVMe 同时通过 PCIe 交换机传输数据,互相挤占带宽。
  • 共享文件系统 IO:多个任务同时写入共享 checkpoint 目录,导致元数据服务器过载,写入延迟从毫秒级飙升至秒级。
  • GPU 显存碎片化:虽然显存总量足够,但碎片化导致无法分配连续大块显存,触发 OOM。

资源竞争的判别需要结合时间维度:如果任务总是在每天的固定时段(如整点 checkpoint 时间)中断,或与其他任务同时启动时中断,则高度怀疑资源竞争。

# 查看 CPU 争抢(容器内)
$ cat /sys/fs/cgroup/cpu/cpu.stat
nr_periods 10000
nr_throttled 3421      # 被节流的周期数
throttled_time 45678901234  # 被节流的总时间(纳秒),约 45.7 秒

# 查看网络重传(宿主机)
$ netstat -s | grep -i "retrans"
    1234 segments retransmited
    56 fast retransmits

4.5 案例复盘:一次“假网络故障”的定位过程

某团队训练 70B 模型,使用 256 张 A100,任务运行约 2 小时后中断。初始日志显示 NCCL 超时,团队首先怀疑网络问题,但检查 IB 交换机与网卡均无丢包。进一步排查发现:

定位过程:

  1. 初步判断:NCCL 超时 → 怀疑网络 → 检查 ibstat 与 ethtool -S,一切正常。
  2. 深入排查:查看系统日志发现 GPU 温度达到 92°C(接近 95°C 保护阈值),风扇全速运转。
  3. 根因确认:机房空调故障导致局部过热,GPU 热保护降频,计算速度下降,NCCL 同步等待时间超过 30 分钟阈值,最终触发 watchdog 超时。
  4. 真实分类:硬件故障(散热)→ 次生表现为网络超时。

这个案例揭示了中断分类的“因果链”特征:表面现象是 NCCL 超时(网络类),但根因是散热失效(硬件类)。因此,在实际排障中,不应孤立地看待某一类中断,而应建立“现象→根因”的映射思维。

4.6 误区与避坑清单

常见误区:

  • 误区一:所有 NCCL 超时都是网络问题。实际上,GPU 降频、CPU 节流、内存带宽不足都可能引发 NCCL 超时。先看硬件健康状态,再查网络。
  • 误区二:硬件故障一定导致进程崩溃。部分硬件错误(如可纠正 ECC)仅记录日志,不中断进程,但会累积并最终引发不可纠正错误。应建立硬件错误日志监控。
  • 误区三:软件错误必然可复现。分布式下的软件错误常因时序、随机种子、数据顺序不同而间歇性出现,不可复现不代表不存在。
  • 误区四:资源竞争只影响性能,不影响正确性。资源竞争导致的超时同样会杀死任务,且由于 checkpoint 可能未及时保存,损失的时间远超预期。

最后,建议团队建立中断分类标签体系,在任务日志中自动标记每次中断的类型(如 hardware/gpu_xid、network/nccl_timeout、software/oom、resource/cpu_throttle),并定期统计各类中断占比。这不仅能指导排障优先级,还能为集群采购、代码优化提供数据支撑。中断分类不是终点,而是建立韧性训练系统的起点。