Chapter 11

OOM、NCCL hang、loss spike 排查指南

📌 本章基于 NVIDIA / GitHub Issues 高频问题 · commit 432d76b2b8bf 。

Megatron 训练大模型时,大部分时间是在"训练前 + 训练中卡住 + 训练崩溃后"中度过的。本章按这三个时段组织。

11.1 训练前:理论显存自查

Megatron 自带 tools/report_theoretical_memory.py,能根据你的配置算理论显存:

python tools/report_theoretical_memory.py \
    --num-layers 80 --hidden-size 8192 --num-attention-heads 64 \
    --num-query-groups 8 --kv-channels 128 --ffn-hidden-size 28672 \
    --seq-length 8192 --max-position-embeddings 8192 \
    --micro-batch-size 1 --global-batch-size 1024 \
    --tensor-model-parallel-size 8 \
    --pipeline-model-parallel-size 4 \
    --bf16 \
    --use-distributed-optimizer

输出包含每张卡的参数 / 梯度 / 优化器 / 激活预估。跑训练前先跑这个,比"启动后等 OOM"快得多。

11.2 OOM:按概率从高到低排查

现象常见原因修复
第 1 步就 OOM 基础配置就装不下 开 selective recompute;升 TP / PP;开 distributed optimizer;降 micro batch
第 50-200 步 OOM 遇到长样本 开 packing;降 --seq-length;过滤异常长样本
save_checkpoint 时 OOM ZeRO-3 / dist optim 时 gather 显存 --ckpt-format torch_dist;或 --async-save
反向 OOM 但前向 OK 梯度没 distribute --use-distributed-optimizer + --overlap-grad-reduce
有的 stage OOM 别的 stage 没事(PP) layer layout 不均 --standalone-embedding-stage / 自定义 layout
fp8 + flash-attn 突然 OOM TE 内部缓存 查 TE 版本;试 NVTE_FUSED_ATTN=0
长上下文 OOM 没开 CP --context-parallel-size 4
VPP 模式 OOM interleaved 每卡持多份激活 降 virtual_pipeline_size 或减 num_microbatches

OOM 工具箱

# 1. 看每卡显存使用峰值
nvidia-smi -l 1

# 2. 用 PyTorch 显存 profiler
torch.cuda.memory._record_memory_history(max_entries=10000)
# ...训练几步...
torch.cuda.memory._dump_snapshot("memdump.pkl")
# 在 https://pytorch.org/memory_viz 打开

# 3. Megatron 自带 wall clock + memory profile
--profile \
--profile-step-start 5 \
--profile-step-end 6

11.3 NCCL hang:调度类问题

"NCCL hang" 是 Megatron 分布式训练的标志性故障 —— 多张卡卡住,没有报错,看起来在干活但其实在干等。原因几乎都是跨 rank 调度不对称

常见原因(按发生率)

原因调试修复
某 rank Python 异常但没 propagate NCCL_DEBUG=INFO TORCH_DISTRIBUTED_DEBUG=DETAIL
跨 rank 模型 forward 路径不一致 print 每 rank shape 检查 if rank==0 这种条件分支
数据 sampler 在某 rank 提前耗尽 查 dataloader length 确认 sampler 走 DistributedSampler
NCCL 拓扑发现失败 nvidia-smi topo -m 检查 NVLink 是否完整
跨节点 ib 抖动 nccl-tests 测带宽 查交换机;隔离故障节点
NCCL 超时太短 默认 30 分钟 NCCL_TIMEOUT=3600 让它 hang 出错而不是直接退出
没设 CUDA_DEVICE_MAX_CONNECTIONS=1 必须设

调 hang 的杀手锏

export NCCL_DEBUG=INFO
export NCCL_DEBUG_SUBSYS=ALL
export TORCH_DISTRIBUTED_DEBUG=DETAIL
export TORCH_NCCL_BLOCKING_WAIT=1
export TORCH_NCCL_TRACE_BUFFER_SIZE=10000

# 启动训练;hang 后 ctrl-C 会打印每个 rank 卡在哪个 NCCL call

11.4 loss spike:训练飞了

大模型预训练经常碰到:训了几千步、loss 缓慢下降,某一步突然飙到 10+ 然后开始震荡发散。原因谱系:

现象多半原因修复路线
fp16 时频繁飞 数值范围窄 换 bf16
bf16 也偶尔飞 梯度爆炸 / 坏样本 --clip-grad 1.0--check-for-nan-in-loss-and-grad;查坏样本
每次 ramp up batch 时飞 batch 突变 → 优化器没准备好 --rampup-batch-size 平滑过渡
训了 1000 步飞、回滚也飞 数据集脏 / 异常长序列 过滤异常样本;查 token 分布
fp8 训练飞 fp8 scaling 还没收敛 前 100 步用 bf16,之后切 fp8
启用 SP 后飞 RNG context 错 查 dropout RNG 实现
大 LR + 大 batch 飞 把 LR 减半;warmup_steps 升 1.5×

恢复策略

  1. 从最近一个 healthy checkpoint 恢复;
  2. 跳过引发 spike 的 batch(用 --skip-train-iteration-range);
  3. 临时降 LR 训几百步,再恢复正常 LR;
  4. --check-for-nan-in-loss-and-grad 提前发现。

11.5 收敛奇怪

现象原因修复
loss 完全不降 LR 太小 / tokenizer 不匹配 / template 错查 LR;验证数据;最小 example dry-run
loss 慢慢降,验证集不降 过拟合 / 数据重复 查数据去重;缩小 epoch
training loss 比 val loss 高 train 没开 eval mode(少见) 检查 dropout
perplexity 异常高 position embedding 类型错 核对 --position-embedding-type
resume 后 loss 跳变 scheduler / optimizer 状态没恢复 不要加 --no-load-optim

11.6 通信 / 性能"哪一步慢"

用 Megatron 自带 wall clock:

--log-throughput \
--log-progress \
--log-timers-to-tensorboard

训几十步后 tensorboard 上能看到分段时间:

计时器含义
forward-compute 前向计算
backward-compute 反向计算
forward-send-backward-recvPP 通信
backward-params-all-reduceDP 梯度同步
optimizer optimizer.step

哪一项占比异常就专项排查。

11.7 启动期常见报错

报错修复
RuntimeError: NCCL error 5: invalid usage 没设 CUDA_DEVICE_MAX_CONNECTIONS=1
AssertionError: num_attention_heads must be divisible by TP调 TP 或 num_heads
cannot find megatron.core._C fused kernel 没编;cd megatron/core/datasets && make
flash_attn import error pip install flash-attn --no-build-isolation
TransformerEngine not found 用 NGC 容器;或 pip install transformer-engine[pytorch]
data path .bin not found 第 6 章 6.13

11.8 多机训练专属问题

现象修复
跨节点 PP 慢 查 IB;NCCL_IB_HCA / NCCL_SOCKET_IFNAME 正确
某节点 GPU 不参与 torchrun--node-rank 写错
不同节点起步时间差几分钟 共享文件系统慢 / 模型从 HF 拉太慢
resume 跨节点失败 checkpoint 没在共享文件系统
NCCL 跨节点带宽极低 iptables / VxLAN 阻挡了 GDR;走 NCCL_NET_GDR_LEVEL

11.9 提 issue 的最小信息清单

  1. Megatron commit hash;
  2. PyTorch / CUDA / NCCL / TransformerEngine 版本;
  3. 启动命令完整复制;
  4. NCCL_DEBUG=INFO + TORCH_DISTRIBUTED_DEBUG=DETAIL 下的完整 log;
  5. 能否在更小配置(如 TP=1 PP=1)复现?
  6. 能否用 docker.io NGC 镜像复现?

11.10 心法

三步走
  1. 能用 NGC 容器就用——绝大多数"奇怪错"在标准镜像里不出现;
  2. 先跑 tools/report_theoretical_memory.py——OOM 不是猜的;
  3. 打开三层 verbose log(NCCL、Distributed、Megatron timers)——比看 stderr 蒙猜效率高 100 倍。