排障与实战
目录
系统排查方法论
8 卡训练任务吞吐比预期低,如何定位?
答:
从外到内(网络 -> 调度 -> 显存 -> 计算)分层排查:
| 步骤 | 检查项 | 工具/方法 |
|---|---|---|
| 1 | CPU 和 IO 是否打满 | top, iostat |
| 2 | 显存和算力利用率 | nvidia-smi |
| 3 | 时间分布 | PyTorch Profiler / Nsight Systems |
Nsight Systems 时间线解读:
时间线:
[绿色 Kernel] [绿色 Kernel] [红色 NCCL] [绿色 Kernel]
↑ 算力瓶颈 算力瓶颈 ↑ 通信瓶颈 算力瓶颈
loss 正常下降,但训练速度慢,优先优化什么?
答:
先确定是 Compute Bound 还是 Memory Bound:
-
确认基础优化是否开启:
- FlashAttention
- TF32/BF16
-
尝试增大 Batch Size 跑满流处理器
-
排查 Host/Device 拷贝:
- 是否有频繁的小数据拷贝打断 CUDA 流
常见故障定位
增加 GPU 数量后吞吐无线性提升,可能原因?
答:
这是典型的 阿姆达尔定律(Amdahl's Law) 体现:
加速比 = 1 / ((1-P) + P/N)
其中 P 是可并行部分比例,N 是处理器数量
具体原因:
- 通信比重上升:节点增加导致跨机 RDMA 通信开销激增
- 单卡负载下降:全局 Batch Size 没有等比例放大,单卡分到的 Micro-batch 太小,变成 Memory-bound,算力无法吃满
解决方案:
- 确保 Global Batch Size 随 GPU 数量等比例增长
- 优化通信拓扑,提高 Overlap 效率
pipeline 某个 stage 特别慢怎么处理?
答:
这是严重的短板效应。
解决办法:
重新做负载均衡(Stage Imbalance Profiling):
- 前几层有 Embedding 词表通信较慢,可以给该 Stage 少分配几个 Transformer 层
- 把多出的层分配给中间空闲的 Stage
优化前:
Stage 0: [Embedding][Layer1][Layer2] → 慢(Embedding 通信重)
Stage 1: [Layer3][Layer4] → 快
Stage 2: [Layer5][Layer6] → 快
优化后:
Stage 0: [Embedding][Layer1] → 减少层数
Stage 1: [Layer2][Layer3][Layer4] → 增加层数
Stage 2: [Layer5][Layer6]
训练中出现 occasional hang(偶尔卡住/慢),常见原因?
答:
| 原因类型 | 具体表现 | 排查方法 |
|---|---|---|
| 网络层面 | 丢包或死锁(如 RoCE 交换机的 PFC 风暴) | 检查交换机日志 |
| 硬件层面 | 某台机器的 GPU 硬件降频(过热或 ECC 错误) | nvidia-smi -q |
| 数据层面 | 某个 step 的文本数据异常的长,没做好截断 | 数据预处理日志 |
扩展性分析
如果 8 张卡扩到 64 张卡,吞吐上不去,你怎么分析?
答:
这是典型的扩展性折损问题。
分析步骤:
-
用 Nsight 看通信占比
- 64 卡跨机 RDMA 速度远不如机内 NVLink
- 可能全在等网络 All-Reduce
-
看 Global Batch Size
- 有没有等比例放大
- 如果没有,单卡分到的数据少了,GPU 就吃不满了
-
检查负载均衡
- 各 Stage/TP 组之间是否均衡
工程价值观
吞吐最大化和工程稳定性哪个更重要?
答:
工程稳定性绝对优先。
大集群一次崩溃或异常停机的财务成本极高(几十万算力费废掉)。不能稳定运行 24 小时的极致吞吐是毫无意义的,只有在保证容错、Checkpoint 健康的前提下,再去抠 MFU。
如何看待"先保证能训起来,再追求极致性能"?
答:
非常认同。分布式系统排错极其困难。
正确的做法:
- 先跑通小规模 Baseline,确保 Loss 正常收敛、梯度正确
- 在这个可复现的基础上,每次只引入一个优化(比如加 ZeRO,加融合算子)
- 如果 Loss 对不上立刻回滚
这是顶尖 Infra 工程师的必修准则。
如果吞吐提升了 20%,但 P99 时延恶化了,你会怎么看?
答:
在商业信任与安全(审核)场景下,这项优化大概率是不可接受的,会被打回。
原因:
- 吞吐提升 20% 只是省了一点机器成本
- P99 恶化意味着在流量晚高峰时,有 1% 的广告无法在规定的时效(比如 200ms)内过审
- 这会直接导致广告投放超时,损失客户体验和真实广告收入
改进策略:
引入动态 Batching 阈值,或将业务进行快慢车道隔离:
- 短审核请求走高优通道
- 长文件审核走离线大 Batch 通道
在保证 P99 绝对不劣化的红线之上,再去抠那 20% 的吞吐收益。
如果让你做一个训练优化项目,你会怎么设计实验验证收益?
答:
控制变量法与 A/B Test。
- 跑 Baseline:锚定 Loss 和 MFU
- 验证数学等价性:在相同 seed 下跑到第 1000 步,Loss 是否能对齐小数点后三位
- 对比吞吐提升:Tokens/sec 的提升
- Profiler 验证:证明瓶颈点真的被消除了
Loss 突刺排查
训练中遇到 Loss 突刺(Spike)的排查思路
答:
Loss 突刺是大模型训练中常见的问题,排查需要系统性地从多个维度定位根因。
排查流程(按优先级):
Loss Spike!
│
├─ 1. 数据层面 ──→ 检查当前 batch 的数据质量
│ • 是否有损坏/异常样本(乱码、超长、空白)
│ • 数据加载是否有 shuffle 异常(某个 batch 全是同类数据)
│ • 检查 DataLoader 是否有 bug(跳过数据、重复数据)
│
├─ 2. 学习率 ──→ 检查 LR scheduler 状态
│ • Warmup 结束瞬间 LR 跳变
│ • Cosine decay 在某些位置的突变
│ • 手动调整 LR 后忘记同步到所有 rank
│
├─ 3. 梯度爆炸 ──→ 检查 gradient norm
│ • 记录每步 grad_norm,spike 前是否已有增长趋势
│ • 是否开启了 gradient clipping(推荐 max_norm=1.0)
│ • 某些层梯度异常大(可能初始化问题或数据问题)
│
├─ 4. 数值不稳定 ──→ 检查精度和 scaling
│ • FP16 训练:Loss Scaling 是否频繁触发 overflow → scale 剧烈振荡
│ • 检查是否有 NaN/Inf(在 loss、grad、param 中插入检查)
│ • 解决:切换 BF16 / 调大初始 loss scale / 降低 LR
│
├─ 5. 硬件问题 ──→ 检查 GPU 和网络
│ • nvidia-smi -q 查看 ECC 错误、温度降频
│ • NVLink/RDMA 链路是否有间歇性故障
│ • 某张卡计算结果 silent corruption → 梯度异常
│
└─ 6. 分布式同步 ──→ 检查梯度聚合
• AllReduce 是否正确完成(有无 hang 或部分失败)
• 不同 rank 的 loss 是否一致
• PP 边界的激活传递是否有数值偏差
常见解决方案:
| 方案 | 效果 | 适用场景 |
|---|---|---|
| Gradient Clipping | 限制梯度幅度 | 必须开启(max_norm=1.0) |
| 降低学习率 | 减小更新幅度 | Spike 频繁时 |
| 跳过异常 batch | 跳过 loss 异常大的 step | 数据质量问题 |
| 切换 BF16 | 避免 FP16 溢出 | 数值不稳定 |
| 增大 batch size | 梯度估计更稳定 | 梯度方差大 |
| Checkpoint 回滚 | 恢复到 spike 前状态 | 严重崩溃时 |
| Z-loss 正则化 | 对 logits 幅度做正则 | PaLM 论文提出的方法 |
面试关键点: 排查 loss spike 的核心思路是"分层定位"——先排除数据问题(最常见),再看数值稳定性,最后查硬件和分布式。工程中应该预先记录 grad_norm、loss_scale、learning_rate 等关键指标,事后分析。
面试金句
"一看 top,CPU 满就是数据加载瓶颈;二看 Nsight Systems 的 Timeline:如果 GPU 呈现大块绿色的 Kernel 执行,就是算力瓶颈;如果大块红色的 NCCL Wait 或 cudaMemcpy,那就是通信或访存瓶颈。"
"工程稳定性绝对优先。不能稳定运行 24 小时的极致吞吐是毫无意义的。"
"分布式系统排错极其困难。先跑通小规模 Baseline,确保 Loss 正常收敛。在这个可复现的基础上,每次只引入一个优化,如果 Loss 对不上立刻回滚。这是顶尖 Infra 工程师的必修准则。"
"Loss Spike 排查顺序:数据质量 → 学习率 → 梯度爆炸 → 数值精度 → 硬件故障 → 分布式同步。90% 的 spike 是数据或数值问题。"