适用读者:要回答"这张卡能不能在 X 毫秒内出一 token""加卡还是加带宽"的人。
前置:S23-J06(四类资源与下界公式)。
覆盖旧文:A-4334 §1.3–§1.4(用几个数字估算一次模型执行 + 需求如何推动架构设计,129 点)→ 129 点。
扩展点:E-S23-016(单步生成的三项容量预算)、E-S23-017(batch 转折点 B* 的推导与适用边界)。
上一篇:S23-J06 · 关键数字:容量、算力、带宽、延迟
下一篇:S23-J08 · 计算图与前向执行(第 2 章)。
1. 一句话结论
一次 token 生成的时间,由"读权重"和"算矩阵"两个下界取较大者决定;对 70B 稠密模型,读权重比算矩阵慢约 148 倍——所以"换更快的卡"几乎没用,"少读数据或分摊读取"才有用。
出处:AI Infra 教材 §1.3 例题 1-1(
id 4334)。模型:DeepSeek-R1-Distill-Llama-70B,硬件:一张 H100 SXM。
2. 题目:10 ms 出一 token,能达到吗
给定:H100 SXM(80 GB / 3.35 TB/s / BF16 稠密 989.4 TFLOP/s),70B 稠密模型,单请求每步生成 1 个 token。
估算条件(原文明确):
① 参数近似 N = 70×10^9,按每参数 1 字节估算主要权重读取量(读入后转 BF16 计算)
② 只计主要权重矩阵的乘加 + 一次完整权重读取
③ 权重读取与矩阵计算充分重叠 → 取两者较大者
④ 容量沿用 73.73 GB(8 比特分组量化 + 附加数据)
3. 第一步:检查容量(E-S23-016)
M_W + M_state + M_work ≤ M_cap
73.73 GB + 2.68 GB(8192 token 的 BF16 KV)+ 2.15 GB(工作区)= 78.56 GB ≤ 80 GB ✅
判据:容量检查不通过,后面算多快都没意义——先过这一关。
4. 第二步:两项时间下界
权重读取:R_W = 70 GB(每参数 1 字节)
T_read ≥ 70 / 3350 ≈ 20.90 ms
矩阵计算:F ≈ 2N = 140 GFLOPs(每个权重一次乘 + 一次加)
T_compute ≥ 140 / 989,400 ≈ 0.1415 ms
| 项 | 时间下界 | 占比 |
|---|---|---|
| 读权重 | 20.90 ms | 99.3% |
| 算矩阵 | 0.1415 ms | 0.7% |
比值 20.90 / 0.1415 ≈ 148 倍。
T_step ≥ max(T_compute, T_read) = max(0.1415, 20.90) = 20.90 ms
结论:目标 10 ms 达不到(单请求、纯权重读取这一模型下)。这不是"优化不够",是硬件的读取下界。
4.1 为什么是 max 而不是相加
数据分块到达时,计算当前块可以同时读下一块。稳定阶段每块都要"读一次、算一次",较慢的一项决定速度。
| 场景 | 时间 |
|---|---|
| 能充分重叠 | max(F/Π, R/β) |
| 完全串行 | F/Π + R/β |
| 强依赖(下一步输入依赖上一步输出) | 逐步相加,且每步都不能省 |
判据:下界是"物理极限",实际耗时永远 ≥ 下界;离下界越远,优化空间越大(MFU/MBU 就是在量这个距离)。
5. 第三步:三种改法,谁有用
| 改法 | 读取下界 | 计算下界 | 结论 |
|---|---|---|---|
| 算力翻倍(989.4 → 1978.8 TFLOP/s) | 20.90 ms | 0.0707 ms | 几乎无改善(仍 20.90 ms) |
| 带宽翻倍(3.35 → 6.7 TB/s) | 10.45 ms | 0.1415 ms | 有效,下界减半 |
| 权重减半(70 → 35 GB) | 10.45 ms | 0.0707 ms | 有效,等价于带宽翻倍 |
| batch 内共享一次权重读取 | 20.90 ms(整批) | 2BN/Π |
吞吐提升,单请求延迟不变 |
判据:先看谁在瓶颈上,再改对应的资源。 算力翻倍对带宽瓶颈无效——这是最常见的错误采购决策。
6. 第四步:batch 的转折点(E-S23-017)
设 batch size 为 B:
容量:M_W = b_W·N (权重存一份)
读取:R_W = b_W·N (每批读一遍)
计算:F ≈ 2·B·N (B 个 token 共享一次权重)
读与算相等的点:2BN/Π = b_W·N/β
⇒ B* = b_W·Π / (2β)
代入 b_W = 1、Π = 989.4×10¹²、β = 3.35×10¹²:
B* = 989.4e12 / (2 × 3.35e12) ≈ 147.7
| batch 范围 | 谁决定时间 | 加 batch 的效果 |
|---|---|---|
| B < 147.7 | 权重读取 | 每个输出分摊的读取时间下降(吞吐上升) |
| B ≈ 147.7 | 两者相等 | 转折点 |
| B > 147.7 | 矩阵计算 | 整批时间近似线性增长 |
原文的关键提醒:B* 只比较了"矩阵运算 vs 权重读取",没有计入各请求的 KV 缓存。按容量预算,一张 H100 放下 73.73 GB 权重后只剩 6.27 GB,装不下 148 条请求的 KV。所以 B* 是"计算侧的理想转折点",实际可达 batch 由容量决定。
6.1 batch=8 的算例
整批读取:70 GB → 20.90 ms
整批计算:2 × 8 × 70e9 = 1,120 GFLOPs → 1,120/989,400 ≈ 1.13 ms
每输出分摊读取:20.90 / 8 ≈ 2.61 ms
吞吐:8 / 0.0209 s ≈ 383 token/s(单请求模型约 47.9 token/s)
判据:"每输出分摊时间"是吞吐口径,不是延迟口径。 每个请求仍要等整批执行完,所以 batch 提吞吐、不提单请求延迟——这一句能避免一半的容量评审争论。
7. 可复算(实测)
本系列提供脚本,输出与正文完全一致:
$ cd /root/博客运营官/blog-v2 && python3 tools/s23_book_calc.py
H100 SXM: 80 GB / 3.35 TB/s / 989.4 TFLOP/s(BF16 稠密)
T_read = 70.00 GB / 3350.00 GB/s = 20.896 ms
T_compute = 140.00 GFLOPs / 989400 GFLOP/s = 0.1415 ms
ratio = 147.7 x
B* = 147.7 (b_W=1)
batch 8 : compute 1.132 ms, per-output read 2.612 ms, tput 382.9 tok/s
batch 32 : compute 4.53 ms
batch 148 : compute 20.94 ms -> 计算开始超读取
容量(8bit, 8k 上下文): 73.73 + 2.68 + 2.15 = 78.56 GB <= 80.0 GB
放完权重剩余 6.27 GB;单条 8192-token KV 2.68 GB → 最多 2 条 8k 请求(未计工作区)
A100 同条件 T_read = 34.3 ms;T_compute = 0.449 ms
最后两行正好印证 §6 的提醒:放完权重只剩 6.27 GB,实际连 3 条 8k 请求都放不下,所以
B*=147.7只是计算侧的理想值。
标注:以上是按原文条件复算(权重读 70 GB、每参数 1 字节、充分重叠),不是线上测量。真实系统的 MBU/MFU 要用 profiler 取。
8. 前提与边界
| 结论 | 成立条件 | 不成立时 |
|---|---|---|
| 读取下界 20.90 ms | 每参数 1 字节、单请求、读取不重叠于其他请求 | 权重更低比特 → 按比例降;多请求 → 分摊 |
| 计算量 2N | 只算主要矩阵乘加 | 长上下文要加 Attention(第 2 章:随上下文长度增长) |
max 取较大者 |
读取与计算可重叠 | 依赖链强 → 相加 |
| B* 是理想值 | 忽略 KV 容量 | 实际 batch 受显存限制 |
9. 常见误区
| 误区 | 纠正 |
|---|---|
| "算力翻倍,生成快一倍" | 带宽瓶颈时几乎无变化(148 倍差距) |
| "batch 越大延迟越低" | batch 提吞吐,单请求延迟反而变长 |
用 B* 直接定线上 batch |
还要过容量这一关(KV + 工作区) |
| 把"每输出分摊时间"当延迟 | 两者差一个 batch 倍数 |
| 只算权重读取,忘记长上下文的 KV 读取 | 长上下文时读取量显著增加 |
10. 自测
- 把 H100 换成 A100 80GB(2.039 TB/s、312 TFLOP/s),同一模型的读取下界是多少?还达得到 10 ms 吗?
- 权重改成 4 比特(0.5 字节/参数),读取下界变成多少?
- batch=32 时,每输出分摊读取时间是多少?单请求延迟变了吗?
- 为什么
B*≈148在实际部署中往往达不到?
答案
70/2039 ≈ 34.3 ms,达不到(更慢)。35 GB / 3350 ≈ 10.45 ms。20.90/32 ≈ 0.65 ms;单请求延迟不变(仍需等整批)。- 因为容量限制:放完权重后剩余显存装不下 148 条请求的 KV。
11. 下一篇
S23-J08 · 计算图与前向执行 —— 第 2 章开始把"2N"这个近似拆开:真实模型里哪些算子是计算密集的、哪些受限于读取,以及注意力为什么随上下文长度增长。