LLM 推理经济学:Batch、带宽与 KV Cache
读完这篇,你会知道这些问题背后的共同答案:
- 为什么同一个模型可以有“快模式”和“慢模式”?
- 为什么输出 token 通常比输入 token 贵?
- 为什么长上下文常在 200K 附近突然涨价?
- 为什么 batch 能把推理成本打下来,但不能无限便宜?
- 为什么 MoE 模型天然适合塞进一个 GPU rack,而跨 rack 会变麻烦?
- 为什么 pipeline parallelism 能省权重显存,却省不了 KV cache?
- 为什么 prompt cache 命中便宜,写入却要按保留时间收费?
- 为什么模型可能会被训练到远超 Chinchilla-optimal?
这些现象看起来像产品定价、模型架构、芯片互联、显存容量各管各的事,但底层其实反复回到同一个判断:一次 token 生成到底是被计算卡住,还是被显存带宽和 KV cache 卡住。
Roofline:一次 Decode 最少要多久
这组公式回答:生成下一个 token 的延迟下界是什么?
一次 decode 至少有两类工作:把激活权重乘一遍,以及从显存取出权重和 KV cache。二者可以部分重叠,但总时间不能低于更慢的那一个。
访谈里为了抓主项,忽略了 attention 里的小计算项,把 KV cache 的主要压力看成显存读取。
| 符号 | 定义 |
|---|---|
| \(t_{\text{compute}}\) | 一次 decode batch 的矩阵乘计算时间。 |
| \(t_{\text{weight}}\) | 从显存读取模型权重的时间。 |
| \(t_{\text{KV}}\) | 从 KV cache 读取上下文历史的时间。 |
| \(B\) | decode batch 中同时生成下一个 token 的序列数。 |
| \(L\) | 每条序列需要 attend 的历史上下文长度。 |
| \(N_{\text{total}}, N_{\text{active}}\) | 总参数量,以及每个 token 实际激活并参与计算的参数量。 |
| \(\mathrm{mem\_bw}\) | 可用于读取权重和 KV cache 的显存带宽。 |
| \(\mathrm{bytes/token}\) | 一个历史 token 在 KV cache 中占用的字节数。 |
Cost / token:为什么 Batch 便宜
这组公式回答:同一张 GPU 跑一次 batch,单 token 成本怎么变?
GPU 费用按时间算,但一次 batch 产出 \(B\) 个 token,所以单 token 成本近似是总时间除以 \(B\)。权重读取是固定成本,除以 \(B\) 后快速下降。
compute 和 KV fetch 都是每个序列各做一次,除以 \(B\) 后不会继续被摊薄。这解释了为什么“慢模式”不能无限便宜。
| 符号 | 定义 |
|---|---|
| \(\mathrm{cost/token}\) | 每生成一个 output token 分摊到的 GPU 时间成本。 |
| \(t\) | 一次 batch forward pass 的总耗时。 |
| \(B\) | 一次 batch 产出的 token 数;decode 时每条序列产出 1 个 token。 |
| \(\mathrm{GPU\_cost/sec}\) | GPU 每秒租用或折旧成本。 |
| \(t_{\text{weight}}/B\) | 权重读取固定成本摊到每个 token 后的成本。 |
| \(t_{\text{compute}}/B, t_{\text{KV}}/B\) | 计算和 KV 读取的 per-token 下界,无法靠继续增大 batch 无限摊薄。 |
最小经济 Batch:什么时候 compute 追上 memory
这组公式回答:为了摊平权重读取,batch 大概要多大?
访谈中先忽略 KV cache,只比较“读一遍所有权重”和“对 batch 里所有 token 做矩阵乘”。令二者相等,就得到 balance batch size。
硬件的 \(\mathrm{FLOPs}/\mathrm{mem\_bw}\) 在许多 GPU 世代上大约稳定在 300 左右,因此 batch 主要由稀疏度决定。
| 符号 | 定义 |
|---|---|
| \(B\) | 让权重读取和计算时间大致打平所需的 batch size。 |
| \(\mathrm{FLOPs}/\mathrm{mem\_bw}\) | 硬件每读取 1 byte 显存数据可提供的计算量,也就是表里的拐点。 |
| \(S\) | 稀疏度,定义为 \(N_{\text{total}}/N_{\text{active}}\)。 |
| \(N_{\text{total}}\) | 需要从显存中保存并读取的总参数量。 |
| \(N_{\text{active}}\) | 每个 token 实际参与矩阵乘的激活参数量。 |
硬件拐点参考
下表里的“拐点”就是 \(\mathrm{FLOPs}/\mathrm{mem\_bw}\)。它给出硬件每读 1 byte 显存数据,理论上能做多少 BF16 FLOPs;这个值越高,越需要更大的 batch 才能把权重读取摊平。
| 加速器 | 年份 | BF16 算力 | HBM 容量 | HBM 带宽 | 拐点 (FLOPs/byte) |
Drain Time (ms) |
|---|---|---|---|---|---|---|
| A100 (80GB) | 2020 | 312 TFLOPS | 80 GB | 2.0 TB/s | 156 | 40.0 |
| H100 (SXM) | 2022 | 989 TFLOPS | 80 GB | 3.35 TB/s | 295 | 23.9 |
| H200 (SXM) | 2024 | 989 TFLOPS | 141 GB | 4.8 TB/s | 206 | 29.4 |
| B200 (SXM) | 2025 | 2250 TFLOPS | 192 GB | 8.0 TB/s | 281 | 24.0 |
| B300 / Blackwell Ultra | 2025 末 | 2250 TFLOPS | 288 GB | 8.0 TB/s | 281 | 36.0 |
| Rubin R200 | 2026 H2 | ~5000 TFLOPS | 288 GB | 22 TB/s | 227 | 13.1 |
| Rubin Ultra | 2027 H2 | ~10000 TFLOPS | 1024 GB | 32 TB/s | 313 | 32.0 |
| AMD MI300X | 2023 | 1307 TFLOPS | 192 GB | 5.3 TB/s | 247 | 36.2 |
| AMD MI325X | 2024 | 1307 TFLOPS | 256 GB | 6.0 TB/s | 218 | 42.7 |
| AMD MI355X | 2025 | 2300 TFLOPS | 288 GB | 8.0 TB/s | 288 | 36.0 |
| AMD MI450/MI455X | 2026 H2 | 10000 TFLOPS | 432 GB | 19.6 TB/s | 510 | 22.0 |
| TPU v5e | 2023 | 197 TFLOPS | 16 GB | 0.82 TB/s | 241 | 19.5 |
| TPU v5p | 2023 | 459 TFLOPS | 95 GB | 2.76 TB/s | 166 | 34.4 |
| TPU v6e (Trillium) | 2024 | 918 TFLOPS | 32 GB | 1.64 TB/s | 560 | 19.5 |
| TPU v7 (Ironwood) | 2026 | 2307 TFLOPS | 192 GB | 7.4 TB/s | 312 | 25.9 |
| TPU v8t (Sunfish, 训练) | 2027 末 | ~3150 TFLOPS | 216 GB | 6.53 TB/s | 482 | 33.1 |
| TPU v8i (Zebrafish, 推理) | 2027 末 | ~2525 TFLOPS | 288 GB | 8.60 TB/s | 294 | 33.5 |
| AWS Trainium3 | 2025 末 | ~1260 TFLOPS | 144 GB | 4.9 TB/s | 257 | 29.4 |
吞吐与“火车发车”
这组公式回答:一个最小经济 batch 对应多少 tokens/s?
访谈把一次 batch 看成一班固定间隔发车的火车。每 \(\Delta t\) 秒发一班,每班产生 \(B\) 个 token,所以吞吐就是 \(B/\Delta t\)。
如果 \(\Delta t\) 是 15 到 20 ms,那么一秒约发 50 到 67 班,视频里用约 64 作为心算值。
| 符号 | 定义 |
|---|---|
| \(\Delta t\) | 两班 batch forward pass 之间的发车间隔。 |
| \(B\) | 每班 batch 处理的序列数,也就是每班产出的 decode token 数。 |
| \(\mathrm{tokens/sec}\) | 该推理配置的输出吞吐。 |
HBM Drain Time:为什么常见延迟是十几毫秒
这组公式回答:为什么一班 batch 的间隔常落在 15 到 20 ms?
如果一次 forward pass 的时间足以把 HBM 读一遍,显存带宽就被充分使用。再慢很多,相当于有时间把同一份 HBM 读多遍,通常没有意义。
| 符号 | 定义 |
|---|---|
| \(t_{\text{drain}}\) | 按满带宽把整块 HBM 读完一遍需要的时间。 |
| \(\mathrm{memory\ capacity}\) | 单卡或单设备 HBM 容量。 |
| \(\mathrm{memory\ bandwidth}\) | 单卡或单设备 HBM 读写带宽。 |
MoE:专家怎么铺到 GPU 上
这组公式回答:稀疏 MoE 的专家数、GPU 数、激活比例是什么关系?
MoE 的核心是总专家很多,但每个 token 只激活一小部分专家。专家并行就是把不同专家放在不同 GPU 上。
这个布局要求 GPU 之间做 all-to-all 通信;在一个 scale-up rack 内通信快,跨 rack 就会慢很多。
| 符号 | 定义 |
|---|---|
| \(\mathrm{experts/GPU}\) | expert parallelism 下每张 GPU 承载的专家数量。 |
| \(\mathrm{total\ experts}\) | MoE 层中全部专家数量。 |
| \(\mathrm{active\ experts}\) | 一个 token 路由时实际调用的专家数量。 |
| \(\mathrm{active\ fraction}\) | 激活专家占总专家的比例,也就是专家层的稀疏激活比例。 |
Pipeline:什么时候跨 rack 可接受
这组公式回答:pipeline stage 之间的 scale-out 通信会不会成为瓶颈?
MoE 层内 all-to-all 会把一个 token 发给多个激活专家,通信量膨胀;pipeline 跨层换 rack 只发送一次激活。即使 scale-out 慢 8 倍,只要层内 all-to-all 工作足够多,跨 rack 就不是主瓶颈。
公式里的 2 来自 MoE all-to-all 的进出两次通信。
| 符号 | 定义 |
|---|---|
| \(\mathrm{mem\_bw}_{\text{scale-up}}\) | rack 内或 pod 内高速互联带宽,例如 NVLink / ICI。 |
| \(\mathrm{mem\_bw}_{\text{scale-out}}\) | 跨 rack / 跨 pod 的网卡或 DCN 带宽。 |
| \(t_{\text{scale-up}}\) | MoE 层内 all-to-all 通信消耗的 scale-up 时间。 |
| \(t_{\text{scale-out}}\) | pipeline stage 换 rack 时跨 scale-out 网络发送激活的时间。 |
| \(\mathrm{active\ experts}\) | 每个 token 在 MoE 层中发送到的专家数。 |
| \(\mathrm{layers/stage}\) | 一个 pipeline stage 在同一 rack 内连续执行的层数。 |
Scale-up / scale-out 参考
上面公式里的 8 是访谈中的粗略假设。实际 scale-up / scale-out 比值随代际变化很大;比值越低,跨 rack pipeline 越容易不成为瓶颈。TPU 行使用 Google Cloud 文档里的 ICI/DCN per-chip 口径;v8 行来自公开报道,scale-out 尚未见官方 per-chip 数字。
| 代际 | Scale-up (NVLink / ICI) | Scale-out (网卡 / DCN) | 比值 |
|---|---|---|---|
| H100 (2022) | 0.9 TB/s | 50 GB/s (400G IB) | 36x |
| B200 (2024) | 1.8 TB/s | 100 GB/s (800G CX8) | 18x |
| Rubin (2026) | 3.6 TB/s | 28.8 TB/s? 实际 ~200 GB/s per GPU | 2~18x¹ |
| Rubin Ultra (2027) | 7.2 TB/s | 更高 | 接近 1:1 |
| TPU v5e (2023) | 0.4 TB/s ICI | 25 Gbps/chip DCN (~3.125 GB/s) | 128x |
| TPU v5p (2023) | 1.2 TB/s ICI | 50 Gbps/chip DCN (~6.25 GB/s) | 192x |
| TPU v6e / Trillium (2024) | 0.8 TB/s ICI | 100 Gbps/chip DCN (~12.5 GB/s) | 64x |
| TPU v7 / Ironwood (2026) | 1.2 TB/s ICI | 100 Gbps/chip DCN (~12.5 GB/s) | 96x |
| TPU v8t / Sunfish (2027 末) | ~2.4 TB/s ICI² | 未公开 | 未公开 |
| TPU v8i / Zebrafish (2027 末) | ~2.4 TB/s ICI² | 未公开 | 未公开 |
² 公开报道给出 TPU v8 ICI 为 19.2 Tb/s per chip,这里按 8 bit/byte 换算为约 2.4 TB/s。
显存容量:Pipeline 为什么省权重但不省 KV
这组公式回答:pipeline parallelism 对每张 GPU 的显存占用有什么影响?
权重可以同时被 expert parallelism 和 pipeline parallelism 分摊,所以 \(P\) 越大,每张 GPU 存的权重越少。
KV cache 看起来也能按 layer 分摊,但为了让 pipeline 不空转,必须同时放进 \(P\) 个 micro-batch。一个 \(P\) 抵消另一个 \(P\),所以每张 GPU 的 KV 项不随 pipeline stages 下降。
| 符号 | 定义 |
|---|---|
| \(C_{\text{total}}\) | 模型权重和 KV cache 加起来的总显存需求。 |
| \(c_{\text{mem}}\) | 分摊到每张 GPU 上的显存需求。 |
| \(E\) | expert parallelism extent,同一层专家横向切到多少个 GPU。 |
| \(P\) | pipeline stages,模型层纵向切到多少个 stage / rack。 |
| \(b\) | 单个 micro-batch 的序列数。 |
| \(B\) | 全局 batch;为了填满 \(P\) 个 stage,稳态近似 \(B=P\cdot b\)。 |
| \(L\cdot\mathrm{bytes/token}\) | 单条序列的 KV cache 显存占用。 |
为什么 \(B=P\cdot b\):如果有 \(P\) 个 pipeline stage,只放 1 个 micro-batch 时,大部分 stage 都在等前一个 stage 传来激活,形成 bubble。为了让每个 stage 同时有活干,稳态时需要 \(P\) 个 micro-batch 同时在途;每个 micro-batch 大小是 \(b\),所以全局 batch 是 \(P\cdot b\)。
\[ c_{\text{mem}} = \frac{N_{\text{total}}}{E\cdot P} + \frac{P\cdot b\cdot L\cdot \mathrm{bytes/token}}{E\cdot P} \] \[ c_{\text{mem}} = \frac{N_{\text{total}}}{E\cdot P} + \frac{b\cdot L\cdot \mathrm{bytes/token}}{E} \]训练 / RL / 推理:为什么可能远超 Chinchilla
这组公式回答:如果最终目标是总成本最低,预训练 token 数该和什么量级相当?
Chinchilla 只优化训练 compute。但产品部署后,模型还会消耗大量推理 compute;RL 也会用 decode 生成轨迹。访谈用启发式:最优点附近,各项成本往往大致均衡。
2022 年 DeepMind 的 Chinchilla 论文结论是:在固定训练算力预算下,模型参数量 \(N\) 和训练 token 数 \(D\) 应该近似等比例扩张。常用经验写法是 \(D_{\text{Chinchilla}}\approx20\cdot N\),也就是每 1 个参数大约配 20 个训练 token。
因此,预训练数据量、RL 数据量、模型生命周期内的推理 token 量会落在相近数量级。若推理规模巨大,就会推动模型比 Chinchilla 推荐值“过训练”很多。
| 符号 | 定义 |
|---|---|
| \(C_{\text{total}}\) | 总 compute 成本,粗略按 FLOPs 或 GPU 时间计。 |
| \(C_{\text{pretrain}}\) | 预训练阶段的 compute 成本。 |
| \(C_{\text{RL}}\) | RL / post-training 阶段的 compute 成本,包括 rollout 生成和训练更新。 |
| \(C_{\text{inference}}\) | 模型上线后服务用户请求的推理 compute 成本。 |
| \(N_{\text{active}}\) | 每个 token 实际参与前向计算的参数量;dense model 里近似等于模型参数量,MoE 里是激活参数量。 |
| \(N\) | Chinchilla 原论文中的 dense model 参数量。 |
| \(D_{\text{pretrain}}\) | 预训练 token 数。 |
| \(D_{\text{RL}}\) | RL 阶段处理的 token 数,包含用于生成/训练的轨迹 token。 |
| \(D_{\text{inference}}\) | 模型生命周期内实际服务出来的推理 token 数。 |
| \(\gamma\) | RL 每 token 的有效 compute 系数;forward-only 约 2,forward+backward 上限约 6,中间还受采样、丢弃轨迹和低 MFU 影响。 |
| \(D_{\text{Chinchilla}}\) | Chinchilla scaling law 建议的训练 token 数。 |
系数 6 来自 transformer 训练常用的 \(6ND\) 估算:一次 forward 约 \(2ND\),backward 和梯度相关计算再带来额外成本。纯 inference 只需要 forward,所以写成 \(2ND\)。
\[ C_{\text{pretrain}} \approx C_{\text{RL}} \approx C_{\text{inference}} \] \[ D_{\text{inference}} = \mathrm{tokens/sec}\cdot \mathrm{deployment\ time} \] \[ 50\mathrm{M/s}\cdot2\mathrm{\ months} \approx 2\cdot10^{14}\ \mathrm{tokens} \] \[ D_{\text{Chinchilla}} \approx 20\cdot N \] \[ 7\mathrm{B}\ \text{params} \Rightarrow D_{\text{Chinchilla}} \approx 140\mathrm{B}\ \text{tokens} \] \[ 70\mathrm{B}\ \text{params} \Rightarrow D_{\text{Chinchilla}} \approx 1.4\mathrm{T}\ \text{tokens} \]这里 \(N\) 是 Chinchilla 原论文里的 dense model 参数量。访谈后面的心算把 frontier MoE 的 active/effective 参数量代进去,是为了做量级估算。
\[ \mathrm{overtraining\ factor} = \frac{D_{\text{pretrain}}}{D_{\text{Chinchilla}}} \approx \frac{200\mathrm{T}}{2\mathrm{T}} = 100 \]长上下文定价:为什么常在 200K 后涨价
这组公式回答:API 在长上下文处涨价,可能透露了什么硬件/模型信息?
如果价格在某个 context length 附近跳档,通常说明这个区间开始显著增加 memory-bound 风险:上下文越长,decode 每一步越可能被 KV cache 读取拖慢。
这里的 \(\mathrm{bytes/token}\) 对应原文里的 “bytes for one token”:不是输入文本 token 本身的大小,而是模型为了让未来 token attend 到这个历史 token,需要在 KV cache 中保存的 key/value 向量大小。
200K 不是物理常数,而是一个产品上好用、工程上合理的阈值:它大致落在现代前沿模型从“主要被计算量限制”转向“更容易被 KV 读取限制”的区间。实际阈值会被模型结构、KV 压缩、稀疏 attention、硬件带宽和产品定价策略共同移动。
背景信息:公开 API 是否按 context length 分档
| 公司 | 是否按 context length 分档 | 关键阈值 | 怎么收费 |
|---|---|---|---|
| OpenAI | 你提供的资料显示部分旗舰模型分 short / long context;我在当前可访问的 OpenAI pricing 页未核到 GPT-5.5 / 272K 这条。 | 约 272K input tokens(待具体 GPT-5.5 页面核验) | 按你给的口径:超过阈值后,long context input 约 2x、output 约 1.5x,并对整次 session/request 应用更高费率。当前可访问的 OpenAI pricing 页面列出了模型 token 价格,但未显示该 GPT-5.5 long-context 档。 |
| Anthropic / Claude | 是。当前官方文档写明 1M context 请求超过 200K tokens 会自动收 premium long-context rates。 | 200K tokens | 官方 context-window 文档写明:超过 200K tokens 的请求按 2x input、1.5x output 的 premium rates 收费;prompt caching 仍按 5m write 1.25x、1h write 2x、cache read 0.1x 叠加。参考 context windows 和 pricing。 |
| Google Gemini | 是。Pro / Priority 等模型明显按 prompt length 分档;Flash / Flash-Lite 等便宜模型不一定分档。 | 200K tokens | Gemini pricing 页按 prompts <= 200K 和 > 200K 分档。例如 Gemini 2.5 Pro 标准价 input $1.25 / MTok <=200K、$2.50 / MTok >200K;output $10 / MTok <=200K、$15 / MTok >200K;context caching 也从 $0.125 到 $0.25。参考 Gemini pricing。 |
| 符号 | 定义 |
|---|---|
| \(L\) | 长上下文长度;公开 API 常在 200K 左右开始设置 long-context 档位。 |
| \(\mathrm{bytes/token}\) | 一个历史 token 的 KV cache 字节数。 |
| \(N_{\text{active}}\) | 每个 token 的激活参数量,决定 decode 计算成本。 |
| \(\mathrm{FLOPs}/\mathrm{mem\_bw}\) | 硬件计算带宽与显存带宽之比。 |
| \(n_{\text{KV heads}}, d_{\text{head}}\) | KV head 数和每个 head 的维度,决定 KV cache 的向量大小。 |
为什么 200K 经常出现:把 \(N_{\text{active}}\) 看成几十 B 到百 B 量级,把 \(\mathrm{FLOPs}/\mathrm{mem\_bw}\) 看成 200~500 FLOPs/byte,把模型工程后的有效 KV 读取看成 KB/token 量级,公式自然会给出十万到数十万 token 的 crossover 区间。
\[ L^\* \sim \frac{50\mathrm{B}\sim150\mathrm{B}} {(200\sim500)\cdot(1\sim3)\mathrm{KB}} \approx 100\mathrm{K}\sim500\mathrm{K} \]因此 200K 更像是这个宽区间里的定价锚点:低于它,多数请求仍能被较好地批处理和摊销;高于它,KV cache 容量、带宽、调度碎片和尾延迟都会更容易恶化,所以 provider 倾向于提高整段请求的价格。
\[ \mathrm{bytes/token} \approx n_{\text{attn layers}}\cdot2\cdot d_{\text{head}}\cdot n_{\text{KV heads}}\cdot\mathrm{bytes/element} \]| 图中符号 | 定义 |
|---|---|
| \(L\) / \(\mathrm{len\_ctx}\) | 当前请求的上下文长度,也就是需要读取多少历史 token 的 KV cache。 |
| \(t_{\text{compute}}(L)\) | 每 token 的计算时间。简化模型里近似不随 \(L\) 增长,所以图中是水平线。 |
| \(t_{\text{mem}}(L)\) | 每 token 的显存读取时间,主要来自 KV cache;随 \(L\) 近似线性增长。 |
| \(L^\*\) | crossover context length,满足 \(t_{\text{compute}}(L^\*)=t_{\text{mem}}(L^\*)\)。200K 是常见产品阈值,不必等同于某个模型的精确物理拐点。 |
| \(t_{\text{cost}}(L)\) | 真实成本下界,取 compute 和 memory 两条曲线中更慢的一条。 |
图形解释
图里的横轴是上下文长度 \(L\)。\(t_{\text{compute}}\) 近似不随 \(L\) 增长,所以画成水平线;\(t_{\text{mem}}\) 随 KV cache 读取长度近似线性上升。实际成本下界取两者的最大值,因此在 crossover 之前近似 compute-bound,之后转为 memory-bound。API 的 tier pricing 通常会把连续成本曲线离散成几档,确保长上下文区间仍覆盖成本。
Prefill vs Decode:为什么输出 token 更贵
这组公式回答:为什么输入 token 常比输出 token 便宜?
decode 的 \(L_{\text{pass}}=1\),每次只生成一个 token,所以 KV 和权重读取无法在很多 token 上摊薄。prefill 一次处理很多输入 token,memory 成本可以除以 \(L_{\text{pass}}\)。
compute per token 大致不变,但 memory per token 随 pass 长度下降。因此如果 decode 价格显著更高,说明 decode 端很可能强烈受 memory bandwidth 限制。
| 符号 | 定义 |
|---|---|
| \(L_{\text{pass}}\) | 一次 forward pass 同时处理的 token 数;decode 为 1,prefill 大于 1。 |
| \(t_{\text{compute, pass}}\) | 整个 pass 的计算时间。 |
| \(t_{\text{compute/token}}\) | 按 pass 内 token 数摊销后的每 token 计算时间。 |
| \(t_{\text{memory/token}}\) | 按 pass 内 token 数摊销后的每 token 显存读取时间。 |
| \(B\) | 同一 pass 并行处理的序列数。 |
Prompt Cache:存 KV 还是重算 KV
这组公式回答:cache hit 为什么便宜,cache write 为什么按保留时间收费?
没有缓存:模型只看到 token id,得从 embedding 开始把整段前缀重新跑一遍 prefill,把每层 KV 重新算出来。多轮对话里前缀越长,浪费越夸张。
缓存命中:KV 已经躺在某个存储层级,只需把字节搬回 HBM 拼上去,省掉整段 prefill 的算力。搬运永远比重算便宜,这是 prompt cache 经济上成立的根本原因。
存储层级三个维度耦合:越快的层级越贵、越小;越便宜的层级越慢、越大。没有既快又便宜又大的选项。
保留时长决定放哪一层:
- 秒级复用:HBM,贵但占用短。
- 分钟级:DDR,单位成本低得多。
- 小时到天级:Flash / disk,慢但极便宜。
热数据待顶层,冷数据沉底层,和 CPU cache、CDN 是同一套分层思路。
| 符号 | 定义 |
|---|---|
| \(\mathrm{cost}_{\text{remat/token}}\) | 缓存失效后,为一个 token 重新计算 KV cache 的成本。 |
| \(\mathrm{hold\ cost}\) | 把 KV cache 保存在某个 memory tier 中每秒占用的机会成本。 |
| \(\mathrm{HBM}, \mathrm{DDR}\) | 不同存储层级;HBM 快但贵,DDR/flash/disk 慢但更便宜。 |
| \(t_{\text{retrieve, DDR}}\) | 把 DDR 中的 KV cache 取回可用层级所需时间。 |
| \(t_{\text{drain}}\) | 按带宽读完整个存储层容量所需时间,用来判断适合的保留时长。 |
存储层级 drain time 量级
| 层级 | 访谈里的 drain time 量级 |
|---|---|
| HBM | \(20\mathrm{ms}\) |
| DDR | \(1\sim10\mathrm{s}\) |
| Flash | \(\sim1\mathrm{min}\) |
| Spinning disk | \(\sim1\mathrm{hour}\) |
Feistel / RevNet:用可逆结构省训练显存
这组公式回答:密码学里的 Feistel 结构如何变成可逆神经网络?
Feistel construction 的关键是:即使 \(f\) 本身不可逆,整个二元映射仍可逆,因为输出中保留了 \(x\)。RevNet 用类似结构让前向激活可以在反向传播时重算,从而少存 activation。
这是“多花 compute,少用 memory”的例子;与 KV cache 的“多用 memory,少花 compute”正好相反。
| 符号 | 定义 |
|---|---|
| \(x,y\) | 可逆 block 的两个输入分量;保留其中一半让整体映射可逆。 |
| \(f(x)\) | 任意不一定可逆的子网络,例如 MLP 或 transformer layer。 |
| \(z\) | 临时记号,表示 \(y+f(x)\)。 |
| \(x_{\text{out}}, y_{\text{out}}\) | 可逆 block 的两个输出分量。 |