今天的大模型,钱的大头不在训练,而在推理。OpenAI 每天要生成超过 1000 亿个词,Cursor 每天产出数十亿行被用户采纳的代码——训练是一次性投入,推理却是 7×24 小时不停地烧。于是"把推理做快、做便宜",成了和"把模型训得更强"同等重要的工程命题。
可推理优化有个反直觉的起点:推理慢,往往不是因为 GPU 算不过来,而是因为它在"等数据"。理解这一点,几乎所有推理优化技术都会变得顺理成章。
本文对应 Datawhale diy-llm 第十章(推理)。原文覆盖面很广但略显发散,这里按一条主线重新组织:先讲清推理与训练的本质区别,再拆开 Prefill / Decode 两阶段与 KV Cache,然后用"算术强度"点破真正的瓶颈、理清延迟与吞吐的矛盾,最后把五花八门的优化技术归到三条路线上。
一、推理与训练:瓶颈从"算力"转向"带宽"
训练和推理虽然跑的是同一个模型,但它们的计算特性几乎相反。
训练时,整条序列的标签都是已知的(ground-truth + 因果掩码),可以一次性并行喂进去算 loss——所有 token 同时计算,GPU 火力全开,瓶颈在算力(FLOPs)。
推理时则是自回归的:每个新 token 都依赖自己刚刚生成的上一个 token,必须一个一个地吐,天然无法在时间维度上并行。这时 GPU 的算力大量闲置,瓶颈转移到了显存与带宽。
| 维度 | 训练 | 推理 |
|---|---|---|
| 输入来源 | 真实标签 + 因果掩码 | 模型自己上一步的输出 |
| 并行化 | 整个序列可并行 | 只能按时间逐步生成 |
| 主要瓶颈 | 算力(compute-bound) | 显存与带宽(memory-bound) |
这个"算力 vs 带宽"的区别,是后面一切推理优化的总根源。
二、Prefill 与 Decode:两阶段与 KV Cache
一次完整推理被切成两段,特性截然不同。
Prefill(预填充):一次性并行处理整个 prompt,逐层算出每个 token 的 Key / Value,存进 KV Cache。这一步和训练一样能并行,算力能打满——它决定了 TTFT(首 token 延迟)。
Decode(解码):逐个生成新 token。新 token 的 Query 只跟缓存里的 K、V 做注意力,算完再把自己的 K、V 追加进缓存:
KV Cache 的意义:在自回归设置里,过去的 token 一旦算完就不会被未来 token 改变,它们对应的 可以复用,避免每生成一个新词就重算整个前缀——这是典型的"用显存换算力"。代价是显存随序列长度线性膨胀:
但 KV Cache 只对"算完就不再改"的自回归模式有效。一旦 token 的表示会被后续修改,缓存就失效了:
| 架构 | KV Cache | 原因 |
|---|---|---|
| 自回归 Transformer | ✅ 适用 | 过去 token 算完不再改变 |
| BERT 等双向注意力 | ❌ 不适用 | 任一 token 改动都影响全局表示 |
| 扩散模型 | ⚠️ 部分适用 | 条件编码可复用,但扩散步骤间会变 |
三、真正的瓶颈:算术强度与"拼车效应"
为什么 decode 这么慢?答案藏在一个叫算术强度(Arithmetic Intensity)的指标里——每从显存搬运 1 字节数据,能喂给计算单元做多少次浮点运算:
每个 GPU 都有一个临界值(Roofline 的拐点):低于它,计算单元算得太快、被迫等数据搬运,是内存受限(memory-bound);高于它,数据喂得过来、算力被榨干,是计算受限(compute-bound)。以 H100 为例:
这个 295 就是 Roofline 曲线的拐点(ridge point):把横轴设为算术强度、纵轴设为实际可达算力,曲线左半段是一条斜率等于带宽的上升直线——此时性能完全由"每秒能搬多少字节"决定,再多的 TFLOPS 也用不上;越过拐点后曲线变成一条水平线,性能被算力峰值锁死。一个算子落在哪一侧,不取决于它有多少 FLOPs,而取决于每搬一字节能摊到多少次运算。
为什么 decode 注定落在左半段?根子在它的计算形态: 时,每一层都是权重矩阵 × 一个激活向量(矩阵–向量乘,GEMV)。每个权重从显存读上来,只参与一次乘加就被丢弃——2 字节权重换 2 次 FLOPs,算术强度天然趋近于 1。整个 7B 模型约 14 GB 的权重,每生成一个 token 就要被完整搬运一遍,而真正用到的运算少得可怜。这正是 decode 慢的物理本质:不是算不过来,是搬不过来。
作为对比,prefill 是权重矩阵 × 一整段提示词的激活矩阵(矩阵–矩阵乘,GEMM),同一份权重被几百上千个 token 复用,算术强度轻松越过 295,因此 prefill 是计算受限的。同一个模型、同一批权重,prefill 吃算力、decode 吃带宽——这个不对称是后面所有优化的出发点。
现在算一笔 decode 的账:批大小 、隐藏维度 、FFN 中间维度 (LLaMA-7B 量级),用 FP16。结果是 FLOPs ≈ 90 亿次、显存搬运 ≈ 180 MB、算术强度 ——远低于 H100 的 295。
def arithmetic_intensity(B, D, F, bytes_per_elem=2):
# 读 X、读权重 W、写结果 Y
bytes_moved = bytes_per_elem * (B * D + D * F + B * F)
flops = 2 * B * D * F
return flops / bytes_moved
# B=1 单条解码:I ≈ 50 ≪ H100 临界 295 → 内存带宽受限
# GPU 大部分时间在等权重从显存搬过来,算力大量闲置结论很扎心:单条解码本质上是内存带宽受限的,再强的算力也派不上用场。
怎么救?关键观察是:decode 搬运的字节里,绝大部分是被所有请求共享的权重,而随请求数增长的只是各自那一小份激活与 KV。于是答案是批处理(batching)= 拼车:把多条请求凑在一起,让它们共享同一次权重搬运。GEMV 也随之变回 GEMM——同一份权重读上来后,被一整批请求各自的激活向量复用。权重只搬一次、却服务了一整批请求,算术强度随 batch 飙升:
| 批大小 B | 算术强度 I |
|---|---|
| 1 | ≈ 50(内存受限) |
| 16 | ≈ 250 |
| 64 | ≈ 700(已越过临界) |
| 256 | ≈ 1400(计算受限) |
batch 越大,越接近甚至越过 295,GPU 从空闲转向饱和,单 token 的推理成本被一整批请求摊薄。这正是 vLLM 等推理引擎拼命做大 batch(连续批处理 / continuous batching)的根本原因。
但拼车不是无限免费的,它有两堵墙。第一堵是显存:batch 里每条请求都拖着自己的 KV Cache,且随各自上下文长度线性增长。权重占掉一块固定显存后,剩下的空间被 KV Cache 瓜分——上下文越长,能塞进同一批的请求就越少, 被显存硬卡住。这也是为什么 KV Cache 的省显存手段(量化、PagedAttention、GQA/MLA)本质上是在给 batch 腾地方。第二堵是延迟:batch 越大,单步计算耗时越长、请求排队越久,吞吐涨了,单条请求的 TPOT 却被拖慢——这就引出下一节那对总在打架的指标。
四、延迟与吞吐:一对常常打架的目标
衡量推理性能有三个核心指标:
- TTFT(Time To First Token):从请求到吐出第一个 token 的延迟,由 prefill 决定,影响"反应快不快"。
- TPOT / Latency:之后每个 token 的生成速度,由 decode 决定,影响"打字流不流畅"。
- Throughput(吞吐量):系统单位时间内生成的总 token 数,衡量整体效率。
关键认知是:高吞吐 ≠ 低延迟。吞吐是系统视角的总效率,延迟是单个用户的真实体验。前面说的"拼车"(大 batch)能大幅提升吞吐,却可能让单条请求排队更久、延迟变高。所以离线批量任务可以一味追吞吐,而在线对话必须优先保延迟——这是一组需要按场景权衡的矛盾。
理解了以上"为什么慢",剩下的优化技术就能归到三条清晰的路线上:省显存的架构、省步数的解码、省输入的压缩。
五、优化路线一:换更省显存的架构
既然瓶颈是显存与带宽,第一条路就是从架构上少存、少搬。
线性注意力 / 状态空间模型(SSM)
标准 softmax 注意力的推理复杂度是 ,而且 KV Cache 随序列长度线性膨胀。瓶颈藏在 里: 是一个 的注意力矩阵,必须先把它显式算出来,复杂度就锁死在 。
线性注意力的破局点是结合律。它把不可分解的 换成一个可分解的核映射 ,于是注意力可以写成 ——先算括号里的 ,得到的是一个与序列长度无关的 矩阵,再左乘 。 的中间矩阵被绕开了,复杂度从 降到 ,长序列下即近似线性。
落到推理上,这个 矩阵就是一份固定大小的状态,靠"前缀累加"边解码边累积,保证因果性——每个词只依赖它之前的信息:
注意这里有个绕不开的代价:那份固定状态本质上是把全部历史压成了一个定长摘要。softmax 注意力保留了每个 token 的 ,能精确回看任意一个历史位置(完美召回);线性注意力只留下一个 的累加和,信息越久越被稀释,因此在"大海捞针"式的精确长程检索上天然偏弱。这正是纯线性模型在质量上常落下风的原因,也解释了为什么主流方案是混合:在大量廉价的线性层里掺入少数几层完整 softmax 注意力,既拿到线性的显存与速度,又保住几层精确召回的能力。
代表工作有 Mamba、S5 这类 SSM,以及 MiniMax 把全局注意力与线性注意力混合的方案。在长上下文下,这种架构的优势是压倒性的——softmax 模型的延迟早早爆炸,而线性/混合注意力几乎只是线性增长:

扩散语言模型:跳出自回归
另一条更激进的路是干脆放弃自回归。自回归把生成步数和序列长度死死绑定:要出 个 token,就得串行跑 次。扩散语言模型换了个思路——先铺开一整段全被掩码(或加噪)的序列,再用若干步迭代去噪,每一步同时预测所有被掩码的位置。这样生成步数(去噪步数)和序列长度解耦,可以在空间维度并行恢复多个 token,不受逐 token 串行的限制,大批量生成时效率很高。
它的软肋也正出在"并行"上:自然语言有强因果依赖,一步并行敲定一大片 token、彼此又看不到对方的最终取值,容易出现局部通顺、全局却前后矛盾——长文本尤其容易逻辑断裂、上下文不一致。
折中方案是块扩散(BDLM):块内用扩散并行恢复被掩码的词元,块间用自回归顺序生成——既拿到块内并行,又能复用 KV Cache、保证跨块连贯。
这条路已经走出了像样的成绩:LLaDA2.0-flash 的平均分达到 73.18,逼近同级自回归模型 Qwen3-30B-Instruct 的 73.60,在复杂生成、代码、数学等任务上甚至更强。
六、优化路线二:用"草稿 + 验证"省掉解码步数
decode 慢的根源是"大模型逐 token 串行"。那能不能让便宜的小模型先冲、大模型只负责检查?这就是一整类草稿 + 验证方法。
推测解码(Speculative Decoding):一个小的草稿模型一口气生成 个候选 token,大模型一次并行验证这 个,接受最长的一致前缀,从第一个不一致处丢弃重来。大模型从"串行生成 步"变成"并行验证 1 次",而且数学上输出分布与大模型单独解码完全一致——这是质量无损的加速。
由此衍生出几个变体:
- 级联解码(Cascade):换个角度,按 token 的不确定性做路由——简单的直接让小模型出,难的才升级到大模型,减少的是大模型的调用频率。
- 推测级联(Speculative Cascades,Google):融合两者,小模型起草一个 block、大模型并行判断其"可接受性",接受则继续、拒绝则由更大模型兜底重写。比纯推测解码延迟更低,比纯级联拒绝率更低。
MTP(Multi-Token Prediction)让模型一次预测多个未来 token,天然契合推测解码。但两家用法完全不同:
DeepSeek V3 把 MTP 当作训练目标,采用按时间顺序的级联结构(在连续隐表示空间里建立条件依赖,而非离散 token 级 rollout),目的是学到更利于多步生成的表示、为后续推测解码打基础——它本身并不直接加速推理。

Gemma 4(2026 年 5 月)则把 MTP 用在推理侧:draft + target 双模型在 token 级做多步草拟 + 验证,直接削减 target 模型的解码开销。
| 维度 | DeepSeek V3 | Gemma 4 |
|---|---|---|
| 作用阶段 | 训练 | 推理 |
| 作用对象 | 隐表示 | Token 序列 |
| 目的 | 增强多步生成一致性 | 减少 target 解码开销 |
| 架构 | 单一主模型 | Draft + Target 双模型 |
七、优化路线三:把输入变短(提示词压缩)
prefill 的成本和 KV Cache 的占用都随 prompt 长度增长,所以第三条路是直接压缩输入。
- 硬压缩:在离散 token 层面动刀——筛选出与查询最相关的句子 / token,或把冗长表达改写得更简洁。
- 软压缩:把上下文编码成连续向量来替代离散 token,更紧凑,但可解释性差、对 prompt 风格敏感。
- 视觉压缩:DeepSeek-OCR 的脑洞——把长文本渲染成图片,再用视觉编码器读回,用固定维度的图像表示来承载长文本。
代价是这些方法本身也有开销(仍需完整前向、可能损失信息),更适合上下文极长且可复用的场景。
总结
把推理优化的全貌收束成几条:
- 根本区别:训练 compute-bound、可整序列并行;推理 memory-bound、必须自回归串行。这是一切的起点。
- 两阶段:Prefill 并行打满算力、决定 TTFT;Decode 逐 token 读写 KV Cache、决定 TPOT,是主要瓶颈所在。
- 算术强度点破本质: 解码 H100 的 295,内存受限;批处理"拼车"是榨干算力、提升吞吐的核心手段。
- 延迟 ≠ 吞吐:大 batch 提吞吐却可能拖慢单条延迟,需按在线 / 离线场景权衡。
- 三条优化路线:省显存的架构(线性注意力 / SSM / 块扩散)、省步数的解码(推测解码 / 级联 / MTP)、省输入的压缩(硬 / 软 / 视觉)。
一句话记住推理优化:大多数时候,GPU 不是在算,而是在等——所有技巧,都是想方设法让它少等一点。
参考资料
- 长上下文语言建模综述(arXiv:2503.17407)。
- DeepSeek-AI, 2024. DeepSeek-V3 Technical Report(arXiv:2412.19437)。
- 大小模型协作 / 推测级联(arXiv:2405.19261)。
- LLaDA2.0 官方报告;Google Gemma 4 推理加速公告。
- Datawhale diy-llm 第十章《推理》(原文)。