4、故障分类与诊断方法:故障类型、日志分析、监控指标、调试工具、根因分析流程

DeepSpeed 训练故障往往不是单一原因造成的,而是配置、硬件、通信、显存、数据与代码逻辑多因素叠加的结果。若没有统一的分类框架和诊断路径,工程师容易陷入“看到什么改什么”的试错循环。本节建立一套可复用的故障分类与诊断方法:先按故障域归类,再用日志与监控指标缩小范围,最后借助调试工具完成根因定位。

一、故障分类:先归类,再定位

DeepSpeed 的故障可以按“发生层次”和“表现形态”两个维度划分。按层次可分为配置层、显存层、通信层、计算层、数据层和硬件层;按表现形态可分为启动失败、训练中断、性能退化、结果异常和静默错误。分类的价值在于:不同类别的首选诊断手段不同,例如通信层优先看 NCCL 日志,显存层优先看 OOM 堆栈与显存快照。

故障域典型表现首选诊断入口
配置层启动即报错、参数不生效ds_config.json 校验、启动命令回显
显存层CUDA OOM、碎片化、峰值突增OOM 堆栈、显存快照、ZeRO stage 配置
通信层NCCL timeout、hang、allreduce 卡住NCCL_DEBUG=INFO、torch.distributed 日志
计算层loss NaN、梯度爆炸、精度异常梯度范数、loss scale 日志、算子检查
数据层dataloader 卡死、样本损坏数据管道日志、单卡复现
硬件层ECC 错误、GPU 掉卡、NVLink 降速nvidia-smi、dmesg、DCGM 指标

二、日志分析:从海量输出中抓关键信号

DeepSpeed 日志分为三类:启动日志、训练步日志和异常堆栈。启动日志关注参数解析与引擎初始化;训练步日志关注 loss、grad norm、lr、step time;异常堆栈关注 Python traceback 与 CUDA/NCCL 错误码。建议在启动时开启分级日志:

export NCCL_DEBUG=INFO
export NCCL_DEBUG_SUBSYS=INIT,COLL
export TORCH_DISTRIBUTED_DEBUG=DETAIL
deepspeed --num_gpus=8 train.py \
  --deepspeed ds_config.json \
  2>&1 | tee train_$(date +%m%d_%H%M).log

分析时遵循“三看”原则:一看首个报错,而非最后一行;二看 rank 编号,定位是全局问题还是单卡问题;三看时间戳,判断是启动阶段、前向阶段还是反向阶段出错。若日志中出现 NCCL timeout,应优先检查网络与 rank 间通信;若出现 CUDA out of memory,则结合 ZeRO stage 与 batch size 分析。

建议为每个实验保留独立日志目录,并在日志头部记录 git commit、ds_config 摘要、GPU 型号与驱动版本,便于事后复盘。

三、监控指标:用数据判断故障边界

日志是离散事件,监控指标是连续信号。DeepSpeed 训练应重点监控以下指标:GPU 利用率、显存占用、显存碎片率、SM 活跃度、NVLink/PCIe 带宽、NCCL 通信耗时、step time、loss 与 grad norm。当 step time 突然上升而 GPU 利用率下降时,通常指向通信瓶颈或数据加载瓶颈;当显存占用持续爬升不释放时,需排查激活值缓存或未释放的中间张量。

DeepSpeed 故障根因分析流程 1. 现象采集 日志/指标/堆栈 2. 故障归类 配置/显存/通信 3. 范围缩小 单卡/单节点/全局 4. 根因验证 最小复现/对照实验 日志分析工具 grep / awk / tee NCCL_DEBUG / TORCH_DEBUG 监控指标工具 nvidia-smi / DCGM TensorBoard / WandB 调试工具 torch.distributed.breakpoint py-spy / gdb / cuda-gdb 根因分析闭环:现象 → 归类 → 缩小 → 验证 → 修复 → 回归 每一步都需保留证据链,避免“改配置碰运气”式排障

四、调试工具:从观察到干预

当日志和指标不足以定位时,需要主动干预。常用工具包括:py-spy dump 抓取 Python 进程堆栈,判断是否卡在通信或数据加载;torch.distributed.breakpoint() 在指定 rank 进入交互式调试;cuda-gdb 定位 CUDA 核函数异常;nsys 与 ncu 分析算子级性能与显存行为。对于通信 hang,可在疑似卡住的 rank 上执行:

py-spy dump --pid $(pgrep -f train.py | head -1)
# 观察是否阻塞在 torch.distributed.all_reduce
# 或阻塞在 DataLoader 的 next() 调用
不要在生产训练任务上直接使用 cuda-gdb 附加进程,可能导致任务中断。建议在最小复现环境或单节点小规模任务中验证。

五、根因分析流程与常见误区

推荐的根因分析流程为:现象采集 → 故障归类 → 范围缩小 → 根因验证 → 修复 → 回归验证。范围缩小是关键步骤,常用“二分法”:先判断是单卡还是全局,再判断是单节点还是多节点,最后判断是配置问题还是代码问题。例如,8 卡训练中仅 rank 3 报 OOM,优先检查该卡是否有其他进程占用或数据分片不均。

常见误区有三:一是只看最后一行报错,忽略首个异常;二是直接调大 batch size 或关闭 ZeRO 来“绕过”问题,掩盖真实根因;三是缺少对照实验,无法确认修复是否有效。复盘时应记录:故障现象、影响范围、根因、修复动作、回归结果和预防措施,形成可检索的故障知识库。

诊断的核心不是“快速改好”,而是“可解释地定位”。每一次故障都应沉淀为分类标签、日志特征和监控阈值,让下一次排障从小时级降到分钟级。