Chapter 11
调试与常见错误
📌 commit 2411b02nanotron 自家代码 = 调试容易
nanotron 调试最大优势:核心代码就 5000 行,遇到问题能 print debug 找。本章给高频问题清单。
11.1启动 / 配置
| 现象 | 处理 |
| "dp * tp * pp != world_size" | 三者乘积必须 = GPU 数 |
| YAML 校验失败 | dataclass 类型严格;看错误指出哪个字段 |
| "dataset folder not found" | Nanoset 路径错;检查 .bin/.idx 文件存在 |
| NCCL hang 在 init | 多机网卡设错;export NCCL_SOCKET_IFNAME |
11.2OOM
| 位置 | 处理 |
| 第 0 step | 降 micro_batch_size;降 sequence_length;增 tp;开 zero_stage=1 |
| 第 N step 突然 | 显存碎片;PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True |
| PP stage 之间不均 | num_hidden_layers 不整除 pp_size;用 interleaved schedule |
11.3NaN / loss 异常
| 现象 | 处理 |
| 0 step NaN | 用 bf16 而非 fp16;init_method.std 调到 0.02 |
| 中途 NaN | lr 过大;clip_grad 设了吗 |
| loss 一直不降 | tokenizer / template / loss mask 错 |
| loss spike 后回归 | 正常,持续才需查 |
11.4TP 调试
| 现象 | 处理 |
| TP 输出跟单卡不一致 | 检查 tp_mode(ALL_REDUCE vs REDUCE_SCATTER 内存布局不同) |
| QKV split 错 | num_attention_heads / num_kv_heads 必须整除 tp_size |
| TP all-reduce 慢 | TP rank 跨 NVLink;让 TP 在节点内 |
11.5PP 调试
| 现象 | 处理 |
| PP send/recv hang | 某 rank 跑了不同分支;统一控制流 |
| num_microbatches 太少 | 气泡占满;增 ≥ 4 × pp_size |
| PP loss reduction 错 | loss 只在最后 stage 有;前面 stage rank 不算 |
11.6checkpoint
| 现象 | 处理 |
| resume 时 mesh 变了报错 | tp/pp size 改了;用 tools 重新切 ckpt |
| save 时部分 rank 卡住 | distributed save 要 barrier;检查 rank 0/其他配合 |
| load 后 loss 比 save 时高 | data sampler 没正确 resume;查 step 是否对 |
11.7调试技巧
# 1) 小模型先跑通
model:
model_config:
num_hidden_layers: 2
hidden_size: 256
# 2) 单卡跑通(dp=1, tp=1, pp=1)
parallelism:
dp: 1
tp: 1
pp: 1
# 3) verbose
export NCCL_DEBUG=INFO
export TORCH_DISTRIBUTED_DEBUG=DETAIL
# 4) print 调试(代码量小,加 print 不怕)
# 比如在 trainer.py 里加 print(f"[rank {rank}] step {step} loss {loss.item()}")
11.8读源码思路
nanotron 源码量小(5000 行),遇到问题直接看实现比读文档快。常用入口:
- 训练循环:
src/nanotron/trainer.py;
- 分布式:
src/nanotron/parallel/;
- 模型:
src/nanotron/models/llama.py;
- 优化器:
src/nanotron/optim/zero.py;
- 配置:
src/nanotron/config/config.py;
- ckpt:
src/nanotron/serialize/。
11.9这章你需要带走的
- nanotron 错误大多明确(dataclass 校验严);
- OOM 优先降 micro_batch / 增 tp / 开 zero;
- PP 调试看 num_microbatches 是否够;
- 调试时直接读源码——只有 5000 行。