章节导航 第 12 章 / 共 16 章
推理优化
从 KV Cache 到推测解码——让大模型跑得又快又省
推理成本的构成
LLM 推理(inference)的成本结构与训练截然不同。训练是一次性投入,而推理是持续运营成本——每一次用户请求都需要实实在在的 GPU 时间。
对于一个 70B 模型,生成一个 token 需要约 FLOPs。在 H100 上(990 TFLOPS BF16),理论上每秒生成约 7000 tokens——但实际上,由于内存带宽瓶颈,只能做到 30-100 tokens/s。
计算密集 vs. 内存密集
LLM 推理有两个截然不同的阶段:
| 阶段 | 名称 | 特点 | 瓶颈 |
|---|---|---|---|
| Prefill | 预填充 | 并行处理整个输入序列 | 计算密集 |
| Decode | 解码 | 逐 token 自回归生成 | 内存带宽密集 |
Prefill 阶段:输入 个 token,一次性计算所有 token 的 KV,类似训练的 forward pass。GPU 利用率高。
Decode 阶段:每步只生成 1 个 token,但需要读取整个 KV Cache。计算量很小(),但内存访问量很大(),GPU 大部分时间在等数据从显存搬到计算单元。
Arithmetic Intensity(算术强度)= FLOPs / Bytes。Decode 阶段的算术强度极低(~1-10),远低于 GPU 的 roofline 拐点(~100-300),因此是内存带宽受限的。
KV Cache:空间换时间
基本原理
自回归生成中,每个新 token 需要与之前所有 token 做 Attention。如果每次都重新计算所有 token 的 ,复杂度是 。
KV Cache 的思路很简单:缓存之前计算过的 ,新 token 只需计算自己的 ,然后与缓存拼接:
Step 1: K = [k_1], V = [v_1]
Step 2: K = [k_1, k_2], V = [v_1, v_2] ← k_1, v_1 来自缓存
Step 3: K = [k_1, k_2, k_3], V = [v_1, v_2, v_3] ← k_1, k_2, v_1, v_2 来自缓存
KV Cache 的显存占用
对于一个典型的 LLM,KV Cache 的大小为:
以 LLaMA 3 70B 为例(80 层,8 个 KV head,128 维,BF16):
| 序列长度 | 单请求 KV Cache | 128 并发 |
|---|---|---|
| 2K | 0.16 GB | 20 GB |
| 8K | 0.64 GB | 82 GB |
| 32K | 2.56 GB | 327 GB |
| 128K | 10.24 GB | 1.3 TB |
KV Cache 的显存占用在长上下文场景下会超过模型权重本身,成为主要的扩展瓶颈。
KV Cache 压缩
适用边界:以下讨论的默认对象是标准 Transformer。对混合架构(线性/循环注意力层 + 少量残留全注意力层,如含 Gated DeltaNet 的模型),KV 的构成不同——循环状态加上残留全注意力层的 KV,且与上下文相关的 cache 需求由残留的全注意力层主导。这类模型不能简单套用 GQA/MQA 的削减思路,需要按 head 分配常驻窗口的独立方法(见本节末尾)。
GQA/MQA(见第 2 章)是最直接的压缩手段——减少 KV head 数量。
其他方法:
- StreamingLLM:只保留 attention sink token + 最近的窗口,丢弃中间的 KV
- H2O(Heavy-Hitter Oracle):根据 attention 分数,只保留”重要” token 的 KV
- SnapKV:在 prefill 阶段识别重要 token,只缓存这些 token 的 KV
- KV Cache 量化:将 KV 从 FP16 量化到 INT8 甚至 INT4,显存减半或减到四分之一
- KVTC(KV Cache Transform Coding)(ICLR 2026):借鉴经典媒体压缩方法,结合 PCA 特征去相关+自适应量化+熵编码。核心洞察:相邻 token 的 KV 向量高度相关,可以用变换编码利用这种空间冗余。实现 4-8x 压缩比且近无损。与 StreamingLLM/H2O 的”选择性丢弃”和量化的”降精度”不同,KVTC 是第三条路径——“利用冗余结构做变换编码”
- FreeKV(ICLR 2026):代表第四条路径——“检索增强”。与 KV dropping(永久丢弃不可恢复)不同,检索增强保留完整 KV Cache,但推理时动态选择子集参与计算。FreeKV 采用三重策略:推测检索(用低精度 KV 快速筛选相关 token)、混合布局(热 token 在 GPU、冷 token 在 CPU/SSD)、双缓冲(检索与计算流水化)。实现 13x 加速,且不丢失信息。
- SpeCache(ICML 2025):属于”检索增强”路径,采用 CPU Offload + 推测预取策略。完整 16-bit KV Cache 卸载到 CPU 内存,GPU 显存中仅保留低精度(1-bit/2-bit)副本。解码时通过低精度副本快速评估 KV 对重要性,同时推测下一个 token 可能关注的 top-k KV 对,提前从 CPU 预取到 GPU——预取与计算并行执行,隐藏 CPU-GPU 通信延迟。SpeCache 桥接了单卡 KV Cache 压缩与后续 PagedAttention/Mooncake 的分布式 KV Store——从”如何在一张卡上压缩 KV”过渡到”如何在 CPU/GPU 间高效调度 KV”。无需重训练,支持 10x KV Cache 压缩比且不丢失信息。
这些方法可以分为五个流派:选择性保留(StreamingLLM/H2O/SnapKV——丢弃不重要的 token)、降精度(量化——用更少的位存储每个值)、冗余压缩(KVTC——利用 token 间的相关性)、检索增强(FreeKV/SpeCache——保留完整 KV 但动态选择子集参与推理,SpeCache 通过 CPU Offload + 推测预取进一步扩展了该路径)、验证换无损(见下)。实际部署中往往组合使用。
第五个流派:验证换无损。 前四个流派都在回答同一个问题——“怎么让压缩后的 KV 尽量准”。但一个容易被忽略的事实是:几乎所有 KV 压缩方法都是有损的。短输出时看不出来,随着解码 token 变多,输出与全 KV 解码的偏离会持续累积,在代码生成与工具调用上可能引发灾难性失败(语法失效、参数不匹配)。
VeriCache(芝加哥大学 + Tensormesh + Microsoft Research)换了个思路:不追求让压缩变准,而是用压缩 KV 起草 token、用完整 KV 验证——把推测解码那套无损保证移植到 KV 压缩上。它成立依赖两条系统性质:(1) 压缩 KV 解码受 HBM 带宽限制、完整 KV 换入受 PCIe/网络限制,两者可以并行;(2) 压缩 KV 的产出常与全 KV 相近,因此可以用很长的起草窗口摊薄每次换入的开销。实测最高 4× 吞吐,且输出与全 KV 推理完全一致。它同时支持 token dropping 与量化两大类压缩器(统一 compressor 接口),还能与常规推测解码复合。
这一流派的意义在于把”有损 vs 无损”从二选一变成了可交易——代价是完整 KV 必须存在于某处(本地 SSD 或远端 store),因此它与后面 §KVCache 中心架构:Mooncake 所代表的 KV 存储层天然互补。
混合架构的 KV 预算:按 head 分配常驻窗口。 HeadWiseKV 处理的是本节开头提到的那类模型。它给每个物理 KV head 分配静态的多级历史窗口,好处是部署前就能预测 cache 需求;分配问题被建模为一个受限的操作率-失真(operational rate-distortion)问题,用 SeqCalib 按执行顺序逐层决策,并条件化于部署时实际使用的低层策略,从而把层间交互纳入考虑;最后由 grouped-cache runtime 把策略落成真实的按 head 的 KV 常驻,而不是”在完整 cache 上加一个掩码”——后者只省了计算,没有省显存。
在 Qwen3.6-27B 上,112K 上下文时采样峰值设备内存降低 8.59%,可验证成功上下文从 114K 扩展到 161K,RULER 与 LoCoMo 上保持接近全 KV 的质量。作者也提示:系统与质量两组结果是分别记录的工作点,不构成联合的质量-系统权衡曲线。
一个容易被忽略的分类维度:分数是怎么跨解码步聚合的。 上面”选择性保留”这一派的绝大多数工作,精力都投在设计更好的 token 打分函数上,而把跨解码步聚合分数的时序规则当成了实现细节。arXiv:2609.03515(EMNLP 2026 方向)在激进压缩设置下系统检验了这个默认假设,得到两个反直觉的结论。
第一,在 EMA(指数移动平均)聚合下,换打分函数几乎不改变淘汰集合。value-norm 与 entropy 变体仍与 attention 高度相关,保留集合几乎不变;但 KeyDiff、key-norm、recency 以及一个学出来的打分器会改变排序并显著劣化。作者把这种稳定性归因于 EMA 聚合本身——它把层间加权与时序保留耦合在了一起。
第二,极端情况下可以干脆不打分。他们试了一个叫 Score-Free decoding 的操作点:只在第一个解码步给完整上下文打一次分,之后冻结该排序、不再打分。在 6 个开源 backbone 与 LongBench / LongBench-v2 / RULER 上,平均质量变化只有 +0.03。提出的 InertiaKV(EMA 型解码期淘汰)与其周期刷新变体 InertiaKV-Lazy,相对全量刷新版取得 1.34–1.46× 解码吞吐。
⚠️ 作者自己给了明确的边界:这些结果不意味着打分质量在一般情况下也无关——它们成立的前提是”激进压缩 + EMA 聚合”这个特定组合。但它足以改变选型时的提问顺序:先问用什么聚合规则、是否全量刷新,再问用哪个打分函数。 顺带一提,上面第 96 行 PRR 用的正是 EMA 预测器,读到这里可以回头检验一下它在激进压缩下的表现。
动态稀疏注意力与推测执行:上述方法均基于”静态选择”——预先决定哪些 KV 对保留、哪些丢弃。DSA(Dynamic Sparse Attention) 代表了一条新路线:每次解码时动态选择 Top-K 相关 KV 块参与注意力计算。但动态选择本身引入了串行化的”选择→注意力”依赖,成为新瓶颈。PRR(Tianyu Wang et al., ACL 2026 Workshop)的解耦方案用三阶段流水化:(1) EMA 预测器推测 Top-K 块;(2) 在真实选择完成前投机执行注意力计算;(3) 当真实选择返回后,用在线 softmax 增量修复内核修补错误块。在多个长上下文基准上,每 token 解码延迟降低最高 40%,下游任务准确率无损。PRR 的核心价值在于展示了 KV Cache 优化正从”怎么丢”到”怎么选”再到”怎么预先猜对选择”演进——推测执行的思想从 token 生成扩展到了 KV 管理。
注意力优化
FlashAttention
FlashAttention(Dao et al., 2022)和 FlashAttention-2 是推理加速的基石。核心思想是IO-aware 算法——利用 GPU 的 SRAM(快但小)和 HBM(慢但大)的层级结构,通过 tiling 减少 HBM 访问:
标准 Attention:
1. 计算 S = QK^T → 写 HBM (O(n²))
2. 计算 P = softmax(S) → 读写 HBM (O(n²))
3. 计算 O = PV → 读 HBM (O(n²))
总 HBM 访问: O(n² + n·d)
FlashAttention:
将 Q, K, V 切成 tiles,在 SRAM 中计算注意力
总 HBM 访问: O(n·d) ← 减少了 O(n²) 项!
FlashAttention 在推理中的加速效果:
| 序列长度 | 标准 Attention | FlashAttention-2 | 加速比 |
|---|---|---|---|
| 2K | 1.0x | 1.7x | 1.7x |
| 8K | 1.0x | 2.4x | 2.4x |
| 32K | 1.0x | 3.8x | 3.8x |
| 128K | OOM | 可运行 | ∞ |
FlashAttention-4(Zadouri et al., 2026-03)针对新一代 GPU(H200/B200)的非对称计算-内存缩放特性,通过内核流水线协同设计实现新一轮加速。核心创新是将内存加载、矩阵乘法和 softmax 形成流水线而非串行——利用 B200 上相对 H100 更快的计算能力与不成比例增长的内存带宽之间的差距。FA-4 已被 vLLM 和主流框架集成,标志着 FlashAttention 系列从”通用 IO-aware”进化为”硬件感知流水线协同设计”。
PagedAttention
PagedAttention(Kwon et al., 2023,vLLM 团队)解决了 KV Cache 的内存碎片问题。
传统方式为每个请求预分配连续显存(按最大序列长度),浪费 60-80% 的 KV Cache 空间。PagedAttention 借鉴操作系统的虚拟内存分页机制:
- 将 KV Cache 划分为固定大小的 page(如 16 tokens)
- 使用 page table 管理逻辑→物理映射
- 按需分配,不浪费
效果:KV Cache 内存利用率从 ~20-40% 提升到 >95%,吞吐量提升 2-4 倍。
MLA 与 FlashMLA
GQA/MQA 通过减少 KV head 数来压缩 KV Cache,但压缩比有上限——最激进的 MQA(只有 1 个 KV head)也只能压缩到 1/H(H 为 query head 数)。
MLA(Multi-Latent Attention)(DeepSeek,2024)走了一条完全不同的路径:将 KV 投影到低秩潜在空间。不减少 head 数量,而是将每个 head 的 KV 通过一个低秩投影压缩到很小的潜在向量。KV Cache 只需要存储这个潜在向量——大小降低约 93%(256 heads → 等效 1 个低维 latent head)。
工程问题在于:MLA 的 decode 阶段需要在线展开潜在向量再做注意力计算,如果实现不好反而会更慢。FlashMLA(DeepSeek 开源)解决了这个问题:
- FP8 KV Cache + BF16 计算:潜在向量用 FP8 存储,注意力计算用 BF16,兼顾压缩和精度
- Token 级稀疏 decode:只对活跃 token 计算,跳过 padding
- 分页 KV Cache:与 PagedAttention 兼容
- H100 优化:在 H100 上达到 410 GB/s 带宽利用率(decode 场景),接近硬件理论上限
目前 DeepSeek V2/V3/R1 均使用 MLA 架构。MLA 与 GQA 的定位关系:GQA 是”减少副本数”,MLA 是”降维压缩”——两种正交的 KV Cache 瘦身策略。
批处理策略
Continuous Batching(连续批处理)
传统 static batching 的问题:一个 batch 中最长的请求完成前,短请求只能空等。
Continuous Batching(也叫 iteration-level batching,Orca, Yu et al., 2022):
- 每个 decode step 检查是否有请求完成
- 完成的请求立即释放资源,新请求立即填入
- GPU 利用率从 <30% 提升到 >80%
Prefill-Decode 分离
Splitwise 和 DistServe 提出将 prefill 和 decode 分到不同的 GPU 上:
Prefill GPU (计算密集) Decode GPU (内存密集)
├── 处理新请求的输入 ├── 逐 token 生成
├── 高 GPU 利用率 ├── 高内存带宽利用率
└── 计算完 KV 后传给 Decode └── 低延迟响应
这样每种 GPU 可以针对自己的工作负载进行优化。
分离之后最痛的不是怎么分,而是比例错了怎么改。 上面与 Mooncake 讲的都是”分到不同 GPU”,却没有回答比例如何定、变了怎么办。真实负载同时存在短时突发与持续的 P/D 需求比漂移——一个此刻配得很好的配置,很快就会错配,即便别处还有空闲容量也会造成延迟 SLO 违规。现有自动扩缩能加容量,但反应慢、需要备用 GPU、且不处理短时尺度的相位失衡。
FluidPD(arXiv:2610.06917,2026-10)给了两个互补机制:
- FluidToken(处理瞬时失衡):decode 侧有空余时,把有界的一部分 prefill 计算卸载到 decode worker;
- FluidRole(处理持续失衡):原地重新指派运行中的 worker 在 prefill / decode 角色之间切换,不用重载模型、不用重启引擎。
两者都由轻量压力指数引导,在 SLO 违规出现之前就暴露两侧的资源压力。在生产 Azure trace 负载上,整体 SLO 达成率相对静态 SGLang 最高提升 94.6 个百分点,且无需额外配置 worker。
⚠️ 这个数必须带参照系:94.6pp 是”最高”(up to)改善幅度,且是相对静态 SGLang 基线而言,不是绝对达成率。基线越差,这个数越大——若丢掉”相对静态 SGLang”这个参照,读者会误读成”达成率 94.6%”。
与 Mooncake 的分工:Mooncake 给了”独立扩缩容”的架构能力,FluidPD 给了”什么时候扩缩、怎么不重启地扩缩”的控制策略。本章 §推理框架 提到的 SGLang Disaggregated Serving 正是它的基线,可以直接接上。
一条理论边界。 分离式架构还带来一个此前未被形式化的调度问题:完成 prefill 的请求,其 prompt KV 会一直占着 prefill 侧显存,直到被准入 decode 池——因此两侧的准入决策是耦合的。该问题被形式化为 Dual-Memory Request Scheduling(DMRS),目标是最小化请求完成时间之和,已被证明为强 NP-hard;目前最好的确定性多项式算法给出统一 36-近似(在 时为 32-近似,arXiv:2610.15579,2026-10)。对教科书定位而言,“这个问题是强 NP-hard、已知最好的近似比是 36”比十个架构图更有信息量。
⚠️ 这是理论结果:两张 H100 上的离线 trace 验证,规模很小,不要写成已在生产中验证的方案。
KVCache 中心架构:Mooncake
Splitwise/DistServe 是”第一代分离”——prefill 和 decode 用不同的 GPU,但 KV Cache 仍然是 GPU 上的临时数据。Mooncake(Moonshot AI,FAST 2025 / CACM 2025)将分离推进到了一个新层次:KV Cache 不再是附属于 GPU 的缓存,而是独立的分布式存储服务。
Mooncake 的三层架构:
Prefill 节点 KVCache Store Decode 节点
├── 处理输入序列 ← RDMA 传输 → ├── 逐 token 生成
├── 生成 KV Cache ├── 多副本存储 ├── 按需拉取 KV
└── 写入 Store ├── 自动淘汰策略 └── 低延迟响应
└── SSD 卸载扩展
关键设计决策:
- KVCache Store 是独立的分布式存储层,支持 RDMA 跨节点传输,不依赖特定 GPU
- 多副本:热门前缀(如系统提示)的 KV Cache 自动创建多副本,避免成为瓶颈
- SSD 卸载:冷 KV Cache 可以卸载到 SSD,显存只保留热数据
- 解耦扩缩容:Prefill 节点、Store 节点、Decode 节点可以独立扩缩
在 Kimi 的长上下文场景(128K+)下,Mooncake 相比传统架构有效请求容量提升 59%~498%(取决于负载特征)。这代表了推理架构从”GPU 中心”到”KV Cache 中心”的范式转变——当上下文越来越长,KV Cache 的管理效率比 GPU 算力更决定系统性能。
Mooncake 2026 H1 生态扩展:
| 时间 | 进展 | 影响 |
|---|---|---|
| 2026-01-28 | FlexKV 分布式 KV Cache 跨集群复用(基于 Mooncake Transfer Engine) | 跨数据中心共享 KV |
| 2026-02-12 | Mooncake 正式加入 PyTorch 生态系统 | 成为 PyTorch 核心组件 |
| 2026-02-25 | SGLang Encoder Global Cache Manager(Mooncake-powered 多模态 embedding 跨实例共享) | 多模态 embedding 复用 |
| 2026-03-19 | TorchSpec 开源(基于 Mooncake 的推理-训练解耦训练框架) | 训练/推理统一架构 |
| 2026-04-29 | SGLang RDMA-based P2P 权重传输(基于 Mooncake TransferEngine),Kimi-K2 1T 模型权重更新从 53s 缩至 7.2s(7x 加速) | 千卡级分布式 RL 关键基础设施 |
| 2026-05-07 | vLLM 官方深度集成 Mooncake Store | 跨实例 KV Cache 共享标准化 |
上表的主题是”KV 怎么存、怎么复用”。但分离式推理还有第三个问题:传输过程本身。长上下文 KV 要跨网络搬运,传输未完成解码就无法开始,因此 KV 传输常常直接决定 TTFT。
Lynx 利用了一个性质——KV cache 不同 bit 的贡献是不等的:高位比特决定注意力的粗结构,低位比特只做精度细化。据此把 KV 拆成两条流:高优先级的 Anchor 流(高位比特)与低优先级的 Residual 流(剩余精度)。Anchor 一到就开始推测解码,Residual 并发传输,最后再用验证保证等价于高精度解码。 效果是 TTFT 接近激进的 4-bit KV 量化,而精度对齐 BF16——相对标准 8-bit KV 量化 TTFT 最多提升 1.43×,相对 SOTA 精度最多提升 5.1%。
这条工作提示的优化方向不止”传得更少”和”传得更快”,还有第三种:边传边用。
推测解码(Speculative Decoding)
基本思想
推测解码(Leviathan et al., 2022; Chen et al., 2023)是近年最巧妙的推理加速技术之一:
- 用一个小的 draft 模型(如 1B)快速生成 个候选 token
- 将这 个 token 送入大的 target 模型一次性验证
- 接受匹配的 token,拒绝不匹配的,从拒绝位置重新采样
关键性质:推测解码在数学上保证与直接用大模型生成的分布完全一致——不损失质量,只加速。
接受率分析
设 draft 模型在位置 生成 token 的概率为 ,target 模型为 ,则接受概率为:
平均每次验证接受的 token 数为:
其中 是第 个位置的平均接受率。draft 模型越好(与 target 分布越接近),接受率越高。
推测解码变体
| 方法 | Draft 来源 | 特点 |
|---|---|---|
| SpecDec | 小型独立模型 | 经典方法 |
| Medusa | 多个预测头 | 无需 draft 模型 |
| EAGLE-3 | 特征级预测 | 融合低/中/高层语义特征,2-6x 加速,NeurIPS 2025,已集成到 vLLM v0.8.5+ 和 SGLang SpecForge(Li et al., 2025-03) | | SpecTr-GBV | 多 draft 并行 | 多 draft 并行 + 块级一次性验证,3.4x 端到端加速(70B 模型) | | Lookahead Decoding | Jacobi 迭代 | 利用自身生成的 n-gram | | Self-Speculative | 跳过层 / 提前退出 | 不需要额外模型 | | QuantSpec | 量化自身(INT4 权重+INT2 KV) | 量化驱动的自推测,不需要独立模型,>90% 接受率,~2.5x 加速 | | BitNest | 位嵌套(低精度 draft 内嵌于高精度 target) | 两个模型共享一份物理权重,draft 侧零额外显存;95.2% 接受率,1.48–1.61×(arXiv:2610.02800,2026-10) |
自推测这一行现在有具体方法了。 表中”Self-Speculative:跳过层 / 提前退出”此前只是一个占位描述。BitNest的构造方向与所有其他方法相反:不是从预定义的 target 派生 draft,而是先构造一个强低精度基座,再通过残差精化恢复高精度 target——于是 draft 与 target 共享同一份物理权重表示(“位嵌套”),draft 侧零额外显存。这个渐进精度设计还被扩展到了 KV cache,因此长上下文同样受益。
多个 7B–8B 端侧友好模型、多种负载下:平均推测接受率 95.2%,且”紧密保持高精度模型的质量”;相对 FP16 自回归解码端到端 1.48–1.61×。在所有代表性自推测基线都支持的 LLaMA 模型上,加速比一致相当或更高。
⚠️ 选型对照,别比错:BitNest 的 1.48–1.61× 低于 QuantSpec 的 ~2.5×,但它的接受率 95.2% 高于 QuantSpec 的 >90%,且 BitNest 面向 7B–8B 端侧 / 显存受限场景,QuantSpec 面向服务端。两者不是替代关系,选择取决于你的瓶颈是显存还是吞吐。
另两条引用纪律:① 1.48–1.61× 是相对 FP16 自回归解码的端到端加速,不是相对其他推测解码方法;② 摘要只说”紧密保持质量”,未给具体基准数字,请勿量化成”无损”。
实际加速效果
| 方法 | 加速比 | 质量损失 |
|---|---|---|
| Speculative Decoding (2-draft) | 1.8-2.5x | 无 |
| Medusa-2 | 2.0-3.0x | 极小 |
| EAGLE-2 | 2.5-3.5x | 无 |
| EAGLE-3 | 2-6x | 无 |
| SpecTr-GBV | 3.4x(70B) | 无 |
| Lookahead | 1.5-2.0x | 无 |
从逐 token 验证到块级验证:经典推测解码每步验证 个候选 token,需要一个一个地比较——第 个 token 被拒绝则后续全部丢弃。SpecTr-GBV 提出的块级验证(Group-level Block Verification)改变了这一范式:将多个 draft token 组成块,用一次 forward pass 同时验证整个块,只有当整个块被拒绝时才回退。这意味着:(1) 验证阶段的延迟从 降为 ;(2) 可以并行生成多个 draft 序列,取接受最长的那个。块级验证代表了推测解码从”逐 token 串行”到”逐块并行”的范式转变,预计将成为后续工作的标准验证策略。
一个被默认、但很少被验证的前提:批量化之后”无损”还成立吗? 上面所有方法讨论的都是单序列层面的输出等价性。生产服务必然是批量的,而批量化恰恰是破坏这一性质的地方。arXiv:2510.22876(Penn State + eBay,EMNLP 2026 Findings)对批量推测解码做了取证分析,发现多个被广泛使用的实现一边报告竞争性速度,一边静默产出损坏输出——重复 token、<unk> 符号——而且这类失败对 ROUGE 之类的聚合指标不可见。
根因是 ragged tensor 问题:不同序列接受的 draft token 数不同,使 batch 内的 position ID、attention mask、KV-cache 三者失同步。作者形式化了两条同步不变量——矩形对齐(rectangular alignment)与 position-ID 连续性(position-ID contiguity)——并证明在连续内存布局下维持它们需要超线性的对齐开销。他们给出的 EQSPEC(不需自定义 kernel 即强制不变量)与 EXSPEC(把等长序列排在一起以绕开重对齐)在 SpecBench、3 个模型族上取得 batch size 8 下 3× 吞吐、与标准解码约 95% 的精确匹配;残差不匹配来自浮点非确定性,而非同步错误。
工程含义:评估一个推测解码实现时,吞吐不是唯一指标,输出等价性应当是一等评估标准——跑得快但产出垃圾不是改进。一个便宜的诊断是看发散形态:立即发散指向 position-ID 错误,逐步劣化指向 KV-cache 漂移。
DSpark:半自回归+置信度调度(DeepSeek+北大,2026-06-27)
DSpark(DeepSeek 联合北京大学,2026-06-27 发布,梁文锋署名)是 2026 H1 推测解码从”算法创新”走向”系统级部署”的标志——已替代 MTP-1 成为 DeepSeek-V4 的生产方案。
核心创新:
- 半自回归草稿架构:并行网络一次性输出整段候选 token,再用轻量级马尔可夫头 / RNN 头补全块内 token 之间的依赖关系——解决了 DFlash 等块级草稿”块内 token 缺乏因果依赖”的痛点
- 置信度动态验证:新增置信度头(confidence head)预测每个候选 token 的接纳概率,配合硬件感知调度器自适应截断低置信度尾部
- 生产性能:相比主流 EAGLE-3,有效生成长度 +26.7%–30.9%(即同等计算量下接受更多 token)
线上真实流量部署数据(DeepSeek-V4 替代 MTP-1 后):
| 场景 | 提速 |
|---|---|
| V4-Flash 单用户生成速度 | 60%-85% |
| V4-Pro 单用户生成速度 | 57%-78% |
| 离线高并发聚合吞吐量 | 51%-400% |
生态扩展:DSpark 训练代码已通过 DeepSpec 开源(同时支持 DSpark/DFlash/Eagle3 三种实现),并已部署到 Qwen3-4B/8B/14B、Gemma4-12B 等第三方模型。
DSpark vs DFlash vs EAGLE-3:三者代表了推测解码的三个工程化阶段——EAGLE-3 是经典逐 token 自回归草稿,DFlash 引入块扩散草稿,DSpark 进一步加入块内因果修正+置信度调度。DSpark 的 60-85% 线上提速代表了推测解码在生产部署中的最高水位。
LongSpec:长上下文推测解码(ACL 2026)
现有推测解码方法几乎全在短文本(<4K tokens)上训练和评估,无法直接用于长上下文场景。LongSpec(Penghui Yang et al., ACL 2026 Long Paper)识别了长上下文 SD 的三个关键挑战并逐一解决:(1) 草稿模型 KV cache 爆炸——设计恒定大小的 KV 缓存草稿模型;(2) 短上下文训练与长上下文推理不匹配——提出位置索引方案缓解训练-推理分布偏移;(3) 树注意力在长序列上低效——注意力聚合策略结合快速前缀计算与标准树注意力。在 5 个长上下文理解数据集上,比 Flash Attention 基线加速最高 3.26×;在 QwQ 模型的 4 个数学推理任务上,墙钟时间减少 2.34×。LongSpec 填补了现有 SD 方法在长上下文场景中的最大盲区——当 1M+ 上下文成为标配时,长上下文推测解码不再是可选项,而是必选项。
另一条解法:压缩草稿侧的记忆,而不是缩小草稿模型。 长上下文 SD 的两难在于——轻量草稿跑得快却抓不住长程依赖,强独立草稿接受率高但草稿侧 KV 访问开销随前缀增长。LongSpec 的解法是让草稿模型自带恒定大小 KV;2608.30252(EMNLP 2026 Findings)选择了相反的一端:保留强独立草稿以保住接受率,改为给它配一份压缩的草稿侧 KV 记忆——由轻量 adaptor 构造并增量更新,保留远端信息的同时维持精确的近期上下文。target 侧仍保留完整 KV 与标准接受/拒绝规则,因此无损保证不变。在 Llama-3.1-8B 与 70B、前缀长至 32K 的设置下,草稿侧显存降低 70%+,加速分别达 2.08× 与 3.33×。
两者的分歧点可以概括为一句话:草稿的能力该省,还是草稿的记忆该省? 这个问题目前没有定论,选择取决于你的瓶颈在草稿模型的算力还是显存带宽。
前面两条都在问草稿侧,那 target 侧装不下怎么办? 这是本章的一个结构性缺口:§KV Cache 压缩 的隐含前提是”KV 就在 GPU 上、只是想压小”,而长上下文生产的真实前提往往是”KV 根本放不进去”。问题陈述很硬:长上下文 serving 在硬件达到有效吞吐之前,先耗尽的是 KV 显存。
HiSparse 把历史放在 host memory、只取回被选中的条目,但它有两个限制:在每一档负载下都用同一个 cache 预算,且不处理 draft 模型的推测解码(如 DSpark、DFlash2)。Adaptive DHiSparse(arXiv:2610.13708,2026-10)补的正是这两件事:
- 在分层稀疏 KV 上支持推测解码——DSpark / DFlash2 保留各自的 proposal 与 acceptance 规则(这点很关键:无损保证不变),共享缺失行的检索、draft KV 用有界窗口的 ring、验证暂存跨层组复用;
- 常驻量随负载自适应——保护必需工作集,GPU 有空余时多留历史,其余通过精确融合检索取回。
| 场景 | 结果 |
|---|---|
| 100K 上下文 / 128 并发,GLM-5.3 + DFlash2 | 793 输出 token/s / decode GPU,为 HiSparse 的 1.45×、非推测自适应 serving 的 1.27× |
| 与 HiSparse 相同延迟上界 | 并发最高 4×,输出 2.3–3.7×(取决于每 token 上界) |
| DeepSeek-V4.1-Flash / 500K 上下文 / 512 并发 + DSpark | 输出为驻留式 serving + DSpark 的 1.85× |
| 负载阶跃(低负载) | 可选常驻把 host 取回从选中行的 14.2% 降到 1.4%,有压力时释放显存 |
🔑 这一节的答案不是”压缩得更狠”,而是”让常驻量随负载浮动”。 固定的 cache 预算必然在某一档负载上错配——低负载时白占显存,高负载时撑不住并发。
与 Mooncake 的关系:Mooncake 解决的是”跨实例共享与 SSD 卸载”,本条解决”单实例内 GPU/host 之间的常驻调度”——是同一问题的两个尺度,可并列使用。
⚠️ 成熟度与归属提示:单篇预印本,无独立复现;数字为作者自评,且依赖特定模型组合(GLM-5.3 + DFlash2、DeepSeek-V4.1-Flash + DSpark)与特定并发档位,跨模型可迁移性未证。arXiv 摘要与作者字段中无机构信息——某中文聚合站称其为”清华团队”,该归属不予采信。
内核级优化
Operator Fusion
将多个顺序操作融合为一个 GPU kernel,减少内存读写:
Before: LayerNorm → Linear → SiLU → Linear
(4次 kernel launch, 4次 HBM 读写)
After: FusedFFN(LayerNorm + Linear + SiLU + Linear)
(1次 kernel launch, 1次 HBM 读写)
CUDA Graph
通过 CUDA Graph 预录制一系列 GPU 操作,避免每步的 CPU→GPU 调度开销。对 decode 阶段(计算量小、launch overhead 占比高)特别有效。
量化推理
在推理时使用低精度计算:
| 精度 | 类型 | 显存 | 速度 | 质量 |
|---|---|---|---|---|
| FP16/BF16 | 标准 | 1x | 1x | 基线 |
| INT8 (W8A8) | 全量化 | 0.5x | ~1.5x | 几乎无损 |
| INT4 (W4A16) | 仅权重量化 | 0.25x | ~1.8x | 轻微损失 |
| FP8 (E4M3) | H100 原生支持 | 0.5x | ~1.8x | 几乎无损 |
| NVFP4 (E2M1) | Blackwell 原生支持 | 0.25x | ~2.5x | per-block scaling,几乎无损 |
NVFP4 的出现改变了大模型部署的经济学——结合 FP4 权重 + FP4 KV Cache + MLA,单张 B200(192GB)可以部署 70B 模型的全精度推理,而之前需要 2 张 H100。
压缩也要分阶段:该压的是 decode,不是 prefill。 上表与 §KV Cache 压缩 的所有手段都是”整个模型一起压”,但本章开头 §计算密集 vs 内存密集 已经确立了两阶段瓶颈不同——这一事实在压缩侧的直接推论此前没人写。
SlimWise(arXiv:2609.34117,2026-09)的前置结论是反直觉的:MoE 每 token 只激活少数专家,但批量解码几乎会访问整个专家池,于是专家权重流量成为主要瓶颈;而 prefill 是计算受限的——剪 prefill 的专家,是牺牲模型质量却换不到多少吞吐。它的做法是按阶段定制专家池:prefill 用全模型,decode 用剪枝模型,且直接复用 prefill 生成的 KV cache,无需转换(免训练的 KV cache 交接)。这个交接在两个 MoE 骨干、三种剪枝准则下”在许多设置中大幅缩小了与全模型的准确率差距”;再加一个只更新少量参数的低成本蒸馏修正残余损失。实现在 vLLM 上,同时支持 PD 分离与 PD 共置。Qwen3.6-35B-A3B 上,50% 专家剪枝下 decode 吞吐最高 1.81×,精度损失极小。
🔴 本条最值得记住的一句:benchmark 准确率可能掩盖剪枝引起的生成长度大幅变化。 分数没掉,不等于行为没变——模型可能只是说话变长或变短了,而这在 pass@1 / 准确率这类聚合指标里是隐形的。
这是本书第三次遇到同一类教训:本章推测解码那节的”输出损坏对 ROUGE 之类的聚合指标不可见”、第 11 章 Terminal-Bench 的”环境整洁度在 pass/fail 里是隐形的”、本条的”生成长度变化被准确率掩盖”。可以合成一条通用判断:聚合指标看不见的失败,是推理优化里最常见的一类回归——每次做压缩类优化,都要单独盯一个聚合指标之外的行为量。
⚠️ 成熟度提示:单篇预印本,无独立复现;Qwen3.6-35B-A3B 单模型、两种 MoE 骨干;“minimal accuracy loss”未给出具体幅度,勿量化成”无损”。
推理框架
vLLM
vLLM 是目前最流行的开源推理框架:
- PagedAttention:高效 KV Cache 管理
- Continuous Batching:动态批处理
- Tensor Parallelism:多卡推理
- Quantization:支持 GPTQ、AWQ、FP8
- OpenAI-compatible API:兼容 OpenAI API 格式
v0.18.0 关键更新(2026-03-20 发布,213 位贡献者、445 commits,史上最大更新):
| 特性 | 说明 | 工程意义 |
|---|---|---|
| GPU-free 渲染 | vllm launch render 命令将多模态预处理(图片解码、音频提取)从 GPU 卸载到 CPU | 成本可降至 GPU 方案的 1.5-5% |
| gRPC 服务 | --grpc flag 启用,HTTP 8000 + gRPC 8001 并行 | 高并发低延迟场景的传输效率提升 |
| FlexKV 后端 | KV Cache 智能 CPU 卸载,只卸载不常用块(冷块),常用块留在 GPU | 单卡可服务更长上下文 |
| 弹性专家并行 NIXL-EP | MoE 模型根据负载动态调整 GPU 数量(Milestone 2) | 异构流量下的资源弹性 |
| NGram 投机解码 GPU 化 | N-gram 草稿生成从 CPU 迁移到 GPU | 降低投机开销,配合异步调度器 |
| 移除 Ray 默认依赖 | 单机部署更轻量,无需启动 Ray 集群 | 简化本地调试和小规模部署 |
| Responses API 流式工具调用 | 边生成边返回工具调用结果 | 适配 Agent 场景下的实时反馈 |
TensorRT-LLM
TensorRT-LLM(NVIDIA)通过编译优化实现极致性能:
- 图优化:算子融合、常量折叠
- FP8 支持:在 H100 上充分利用 FP8 Tensor Core
- In-flight Batching:NVIDIA 版连续批处理
- 量化:SmoothQuant、INT8/FP8 KV Cache
SGLang
SGLang(LMSYS 团队)在 2025-2026 年迅速崛起,在多个场景下吞吐量超过 vLLM:
- RadixAttention:自动 KV Cache 复用(前缀共享),前缀密集型负载下比 vLLM 快 6.4x
- Constrained Decoding:JSON schema、正则表达式约束输出
- Fork/Join 并行:多个生成分支并行执行
- Disaggregated Serving:Prefill 和 Decode 阶段分离到不同的 GPU 集群
2026 格局:SGLang 在 H100 上实测 16,200 tok/s vs vLLM 的 12,500 tok/s(Llama 3.1 70B),特别在结构化输出和前缀缓存场景下优势明显。但 vLLM 的硬件支持更广(TPU、Trainium 等)。
llama.cpp
llama.cpp 是纯 C/C++ 实现的 CPU/GPU 推理引擎:
- GGUF 量化格式:支持 Q2 到 Q8 多种精度
- 跨平台:macOS (Metal), Linux (CUDA/ROCm), Windows
- 消费级硬件友好:MacBook 就能跑 70B 模型(量化后)
推理成本优化实战
典型部署配置(70B 模型)
| 配置 | GPU | 吞吐量 | 成本/1M tokens |
|---|---|---|---|
| FP16, TP=4 | 4x H100 | ~2000 tok/s | ~$0.30 |
| INT8, TP=2 | 2x H100 | ~2500 tok/s | ~$0.12 |
| FP8, TP=2 | 2x H100 | ~3000 tok/s | ~$0.10 |
| AWQ-4bit, TP=1 | 1x H100 | ~1500 tok/s | ~$0.08 |
| FP4+MLA, TP=1 | 1x B200 | ~4000 tok/s | ~$0.06 |
优化检查清单
□ 使用 GQA/MQA/MLA 减少 KV Cache(模型选型时)
□ 开启 FlashAttention / FlashMLA(默认应该开)
□ 使用 PagedAttention(vLLM/SGLang/TRT-LLM)
□ 开启 Continuous Batching
□ 权重量化到 INT8 或 FP8
□ KV Cache 量化到 INT8 / FP8
□ 开启 CUDA Graph(decode 阶段)
□ 推测解码(延迟敏感场景)
□ 前缀缓存 / RadixAttention(多轮对话 / 系统提示复用)
□ Prefill-Decode 分离(大规模部署,SGLang disaggregated serving)
□ 对推理模型:限制最大思考 token 数,防止成本失控
章节小结
- LLM 推理的核心瓶颈是 decode 阶段的内存带宽,不是计算
- KV Cache 是空间换时间的核心机制,管理好它(PagedAttention、压缩、量化)是关键
- 推测解码 是唯一”免费午餐”——加速但不损失质量
- Continuous Batching 将 GPU 利用率从 <30% 提升到 >80%
- 实际部署中,上述技术组合使用,往往能实现 5-10 倍的成本降低