🏠 总目录📚 本教程 可观测性与成本
📑 本页目录(点开跳转)

23 · 可观测性与成本

26 分钟 | ⭐ 让优化变成一件可管理的事


🎯 一句话

你无法优化你没有测量的东西。 这一章把前面 22 章的所有指标收拢成一套可以长期运行的观测体系 —— 以及一份"钱到底花在哪"的账。


📊 一、四层指标体系

每千次请求成本 / 每百万 token 成本 ⭐
  • 用户感知延迟 P95/P99
QPS、吞吐、排队长度、错误率
  • KV Cache 使用率 ⭐⭐、抢占次数
MFU ⭐、单步时间、各阶段耗时占比
  • 通信/计算重叠率、数据管线吞吐
GPU 利用率、显存、带宽利用率 ⭐
  • NVLink/网络流量、温度、功耗、ECC 计数

🔑 诊断的正确方向是【从上往下】: 先看业务指标异常,再逐层下钻找原因。 反过来(盯着 GPU 利用率优化)会让你优化一堆不影响业务的东西。


🎯 二、每一层最该盯的那一个

最该盯的指标 为什么
业务 每百万 token 成本 唯一能和钱直接对应的数字
服务 KV Cache 使用率 比 GPU 利用率更早的容量预警(第 20 章
框架 MFU 唯一能回答"还剩多少空间"(第 4 章
硬件 带宽利用率 大部分负载是带宽瓶颈(第 3 章

⚠️ nvidia-smi 的 GPU-Util 不在这个列表里 —— 第 2 章说过, 它只表示"有 kernel 在跑",一个只用 5% 算力的 kernel 也显示 100%它几乎没有诊断价值。

# ⭐ 训练时该记的最小指标集
import torch
metrics = {
    "loss": loss.item(),
    "grad_norm": gn.item(),
    "lr": sched.get_last_lr()[0],
    "mfu": compute_mfu(tokens_per_sec),           # 第 4 章
    "step_time_ms": dt * 1000,
    "data_wait_ms": data_wait * 1000,             # ⭐ 数据等待时间
    "mem_alloc_gb": torch.cuda.max_memory_allocated() / 1e9,
    "mem_reserved_gb": torch.cuda.max_memory_reserved() / 1e9,  # ⭐ 差值=碎片
    "tokens_seen": total_tokens,
}

💰 三、成本模型:钱花在哪

   训练总成本 = GPU 小时数 × 单价
              = (6 × N × D) / (卡数 × 峰值FLOPS × MFU) / 3600 × 卡数 × 单价

   ⭐ 简化后:训练成本 ∝ 1 / MFU

   → MFU 从 25% 提到 50%,成本【直接减半】
def training_cost(params_B, tokens_T, n_gpus, mfu,
                  peak_tflops=312, hourly=2.0):
    flops = 6 * params_B * 1e9 * tokens_T * 1e12
    seconds = flops / (n_gpus * peak_tflops * 1e12 * mfu)
    return seconds / 3600 * n_gpus * hourly, seconds / 86400

cost, days = training_cost(7, 1.0, 64, 0.45)
print(f"MFU 45%: ${cost:,.0f}{days:.0f} 天")   # $6,912,54 天
cost, days = training_cost(7, 1.0, 64, 0.25)
print(f"MFU 25%: ${cost:,.0f}{days:.0f} 天")   # $12,442,97 天  ⭐ 多花 80%

推理成本的三个杠杆

   每百万 token 成本 = GPU 时价 ÷ (吞吐 × 3600 × 利用率) × 1e6

   ⭐ 三个杠杆,收益依次递减:
   ① 提高吞吐        (量化、连续批处理、更好的引擎)→ 常有 5-10 倍空间
   ② 提高平均利用率  (把离线任务填到低峰期)        → 常有 2 倍空间 ⭐
   ③ 换更便宜的卡    (量化后可能装得下)            → 1.5-3 倍

第 ② 条最容易被忽略: 很多服务的日间峰值和夜间低谷差 5 倍以上, 但集群是按峰值买的。把批量推理、评测、数据处理这类可延迟的任务 调度到低峰期,等于免费拿到大量算力。


🔬 四、profiling 工具链

工具 用途
PyTorch Profiler 最常用,能看 kernel 时间线和显存(第 4 章
Nsight Systems 系统级时间线,看通信/计算重叠最好用
Nsight Compute 单个 kernel 的深度分析(算术强度、occupancy)
DCGM 集群级 GPU 监控,Prometheus 集成
torch.cuda.memory_viz 显存快照可视化(第 9 章
# ⭐ Nsight Systems:看多卡的通信和计算是否重叠
nsys profile -t cuda,nvtx,nccl -o report python train.py

# 给代码段打标记,在时间线上能看到
import torch.cuda.nvtx as nvtx
with nvtx.range("forward"):   out = model(x)
with nvtx.range("backward"):  loss.backward()
with nvtx.range("optimizer"): opt.step()
# ⭐ 这样在 Nsight 时间线上能一眼看出各阶段占比

💡 什么时候用 Nsight 而不是 PyTorch Profiler当你怀疑通信没有和计算重叠时。 PyTorch Profiler 能看到 nccl kernel 的耗时, 但 Nsight Systems 能直观看到它们在时间线上是并排还是串行的


🧭 五、一套可复用的优化流程

   ① 建立基线
      · 记录当前 MFU / 吞吐 / 成本
      · ⭐ 没有基线就没有"改进",只有"感觉变快了"

   ② 定位瓶颈(按顺序排除)
      · 数据管线?    → 换随机张量测(第 22 章)
      · 通信?        → 单卡 vs 多卡对比
      · 显存/碎片?   → memory snapshot
      · 算子?        → profiler 看 top kernel
      · 算力/带宽?   → 算算术强度(第 3 章)

   ③ 只改一件事,然后测
      · ⭐ 同时改两个,你不知道是哪个起作用
      · 也不知道它们有没有互相抵消

   ④ 记录到实验表
      · 改动、MFU、吞吐、成本、结论

   ⑤ 回到 ②

🔑 这个流程和 Kaggle 方法论ML 基础的调试手册是同构的建立基线 → 定位瓶颈 → 单变量实验 → 记录。 领域不同,方法论一样。


📋 六、一张诊断速查表

症状 最可能的原因 去哪一章
MFU < 20% 数据管线没喂饱 22
单卡快、多卡慢 通信瓶颈 / 拓扑不对 0514
OOM 但 batch=1 也 OOM 优化器状态 0911
显存够却报 OOM 碎片 09
开了 AMP 没变快 维度没对齐 / 模型太小 06
torch.compile 没提速 graph break 07
推理吞吐低 KV Cache 碎片 / 没用连续批处理 1617
解码速度慢 带宽瓶颈,考虑量化 1518
TPOT 有毛刺 长 prefill 插队 17
训练卡死无报错 AllReduce 挂死 1021
loss 突然尖峰 异常数据 / FP16 溢出 2106

🔗 和站内其他章的关系

相关的地方 这里的位置
第 4 章 MFU 框架层的核心指标
第 20 章 KV Cache 使用率 服务层的核心指标
第 1 章 先测再优化 本章是那句话的完整流程
ML 基础第 11 章 同构的方法论

✅ 检查点

  1. 四层指标体系是什么?诊断该从哪一层开始?
  2. 每一层最该盯的指标各是什么?
  3. 为什么 nvidia-smi 的 GPU-Util 不在名单里?
  4. 训练成本和 MFU 是什么关系?MFU 从 25% 到 50% 省多少?
  5. 推理降成本的三个杠杆?哪个最容易被忽略?
  6. 什么时候该用 Nsight Systems 而不是 PyTorch Profiler?
  7. 优化流程的五步是什么?为什么"只改一件事"?
  8. "MFU < 20%" 最可能是什么原因?
👀 答案
  1. 业务层 / 服务层 / 框架层 / 硬件层。诊断应该从上往下——先看业务指标异常再逐层下钻。反过来盯着 GPU 利用率优化会优化一堆不影响业务的东西
  2. 业务层:每百万 token 成本;服务层:KV Cache 使用率;框架层:MFU;硬件层:带宽利用率
  3. 因为它只表示"有 kernel 在跑",一个只用 5% 算力的 kernel 也显示 100%——几乎没有诊断价值。
  4. 训练成本 ∝ 1/MFU。MFU 从 25% 提到 50%,成本直接减半(例子里从 $12,442/97 天降到 $6,912/54 天)。
  5. ①提高吞吐(5-10 倍空间)②提高平均利用率(2 倍空间)③换更便宜的卡。第 ② 条最容易被忽略——日夜峰谷差 5 倍以上但集群按峰值买,把可延迟的批量任务调度到低峰期等于免费拿算力。
  6. 当你怀疑通信没有和计算重叠时。PyTorch Profiler 能看到 nccl kernel 耗时,但 Nsight Systems 能直观看到它们在时间线上是并排还是串行
  7. ①建立基线 ②定位瓶颈 ③只改一件事然后测 ④记录到实验表 ⑤回到②。只改一件事是因为同时改两个你不知道是哪个起作用,也不知道它们有没有互相抵消
  8. 数据管线没喂饱(第 22 章)。

🛑 可以停在这里

走神救援

你无法优化你没有测量的东西四层指标:业务(每百万 token 成本)/ 服务(⭐⭐KV Cache 使用率,比 GPU 利用率更早的容量预警)/ 框架(⭐MFU,唯一能回答"还剩多少空间")/ 硬件(⭐带宽利用率);⭐诊断要从上往下——反过来盯 GPU 利用率会优化一堆不影响业务的东西。⚠️nvidia-smi 的 GPU-Util 不在名单里(只表示"有 kernel 在跑",5% 算力也显示 100%,几乎没有诊断价值)。⭐⭐训练成本 ∝ 1/MFU——MFU 从 25% 提到 50% 成本直接减半($12,442/97天 → $6,912/54天)。推理降成本三杠杆:提吞吐(5-10 倍空间)、⭐提平均利用率(2 倍空间,最容易被忽略——日夜峰谷差 5 倍但集群按峰值买,把可延迟的批量任务填到低峰期等于免费拿算力)、换便宜的卡。工具:PyTorch Profiler 最常用,⭐怀疑通信没和计算重叠时用 Nsight Systems(能直观看到时间线上是并排还是串行),配 nvtx.range 打标记。⭐优化流程五步:①建立基线(没有基线就只有"感觉变快了")②按序定位瓶颈(数据管线→通信→显存→算子→算力/带宽)③⭐只改一件事再测(同时改两个不知道是哪个起作用,也不知道有没有互相抵消)④记录 ⑤回到②——和 Kaggle 方法论、ML 调试手册同构记住那张诊断速查表:MFU<20% 查数据管线、单卡快多卡慢查通信、显存够却 OOM 是碎片、AMP 没提速查维度对齐、compile 没提速查 graph break、训练卡死无报错是 AllReduce 挂死。

下一节 👉 24-实战与挑战项目.md

打卡记录保存在你的浏览器里,首页能看到总进度