AI 基建
0%
第五部分 · 推断与服务 · 第 33 章

更快的解码

作者Changkun Ou
阅读时长约 14 分钟

一个以批大小为一运行的前沿模型,大部分时间都在等待。为产出一个词元,它要把每一个权重从高带宽内存流入加速器的计算单元,做一次乘法,然后丢弃。矩阵乘法是瘦长的,一个向量去乘每个权重矩阵,于是芯片在下一批权重到达之前早已把算术做完,随后空等内存。第 31 章第 32 章 从服务一侧确立了这个瓶颈:解码受内存限制,算术强度远低于硬件所能维持的水平。更快的解码正是利用这段闲置算力,改写「一次传播一个词元」的规则:一个廉价过程猜出若干未来词元,昂贵模型用一次目标传播验证多个猜测。解码一个词元,就是从模型在整个词表上给出的概率分布里把它采样出来;所谓目标分布,不过是昂贵模型对下一个词元给出的那组概率。推测解码(speculative decoding)就是这个模式的精确版本:草稿模型先提出词元,目标模型并行验证它们,同时保持目标分布不变。Medusa、Hydra、EAGLE 系列、前瞻解码(lookahead decoding)与多词元预测,主要差别在于猜测从何而来。加速不是方法自身的固定属性。它在小批大小的内存受限场景中成立,因为闲置 FLOPs 确实存在;一旦服务转为算力受限,它就可能消失。

基本动作

自回归生成有一个看似根本的顺序瓶颈:解码 KK 个词元要 KK 次前向传播,每一次都要等它前面那一次。这个瓶颈最直接地体现在用户感知到的延迟上。第 30 章 中的推理模型会在给出答案之前输出长串的中间词元,于是实际耗时由纯粹的顺序解码步数所主导。

本章一切的背后只有一个思想:用额外的并行算力去换更少的顺序步数。一个廉价的过程猜出若干未来词元,昂贵的模型在一次前向传播中检验它们全部,每一个通过检验的猜测,就是一个无需为其单独走一步的词元。因为对 γ\gamma 个候选词元做一次前向传播,几乎与对一个词元做一次传播同价,那些闲置算力几乎不额外增加成本。

有两个量主宰着收益。接受率 α\alpha 是目标保留的草稿词元的比例;草稿成本是猜测者比目标便宜多少。这里 α\alpha 越高,说明草稿越像目标模型会自己采出的续写,每次目标传播所产出的期望词元数也随之上升。关键在于让草稿既廉价又与目标对齐,并一次验证许多候选。后面的讨论围绕两个问题展开:猜测从何而来,以及检验如何保持正确。

图 33.1 把收益画得更具体。在接受率 α\alpha 与一次传播检验 γ\gamma 个草稿词元之下,其中 γ\gamma 是草稿长度,每次目标传播发出的期望词元数是几何级数和 (1αγ+1)/(1α)(1 - \alpha^{\gamma+1}) / (1 - \alpha)。这个式子把「连续接受多少个草稿词元」求和,从一个也不被接受时的一,升向全部被接受时的 γ+1\gamma + 1。更长的草稿只在 α\alpha 高时才有帮助,因为一次早早的拒绝会浪费掉整条尾巴。

2026-06-23T21:05:51.171359 image/svg+xml Matplotlib v3.11.0, https://matplotlib.org/ 0.0 0.2 0.4 0.6 0.8 1.0 接受率 alpha 0 2 4 6 8 每次目标模型通过的期望词元数 基线:每次通过一个词元 草稿长度 gamma = 2 草稿长度 gamma = 4 草稿长度 gamma = 8
图 33.1. 投机解码收益的示意图:每次目标传播发出的期望词元数随接受率变化,并给出若干草稿长度。更长的草稿只在接受率高时才有帮助。据 Leviathan 等(2023)。

试着直接模拟接受/拒绝循环,看蒙特卡洛平均值如何收敛到闭式的几何级数和。

import numpy as np
rng = np.random.default_rng(0)
alpha, gamma, trials = 0.7, 4, 50000

def simulate():
    emitted = np.ones(trials)            # 修正/奖励词元
    alive = np.ones(trials, dtype=bool)  # 尚未被拒绝的运行
    for _ in range(gamma):
        accept = (rng.random(trials) < alpha) & alive
        emitted += accept                # 计入每个被接受的草稿词元
        alive &= accept                  # 在首次拒绝处停止
    return emitted.mean()

closed_form = (1 - alpha**(gamma + 1)) / (1 - alpha)
print(f"simulated mean tokens/pass: {simulate():.4f}")
print(f"closed-form  tokens/pass:   {closed_form:.4f}")

让检验保持精确

决定性的设计抉择,是验证如何保住正确性;而真正让这套方法可以放心部署的,是它可以做到精确。推测解码由 Leviathan 等 (Leviathan et al. 2023) 与 Chen 等 (Chen et al. 2023) 独立提出,正保证了这一点。一个小的草稿模型提出一段 γ\gamma 个词元的续写。目标模型在一次并行传播中给所有 γ\gamma 个位置打分,在每个位置同时给出它自己的分布 pp 与草稿的分布 qq。这里 pp 是最终必须保持不变的目标分布,qq 是便宜草稿分布。一条修正过的拒绝采样规则随后从左到右逐个接受或拒绝草稿词元:从 qq 提出的词元 xx 以概率 min(1,p(x)/q(x))\min(1, p(x)/q(x)) 被接受,而在第一次拒绝处,从残差分布 max(0,pq)\max(0, p - q) 归一化后重采样出一个修正词元。这个残差只保留目标分布比草稿分布多出来的概率质量,用来补回被拒绝处的缺口。这条规则背后的定理是:被接受的词元流,其分布恰如它逐词元地从 pp 采样而来 (Leviathan et al. 2023)。加速是真实的,而输出分布丝毫未动。该方法不是对模型的近似,它就是同一个模型,只不过换了个顺序来采样。

廉价的草稿模型猜出一段 γ 个词元,每个都从它自己的分布 q 采样而来。
一次目标传播同时给所有 γ 个位置打分,在每个位置给出真实分布 p 与草稿分布 q。
沿草稿逐个推进,只要 p(x)/q(x) ≥ r(r 为 [0,1) 上的均匀采样)就接受词元 x。
在第一个未通过检验的词元处停下:它之前的一切,就是最长的有效前缀。
把被拒绝的词元换成从残差 max(0, p − q) 归一化后重采样得到的修正词元。
当整段草稿都被接受,目标自身的那次传播已几乎不额外增加成本地给出一个词元。
图 33.2. 逐步走过这条修正过的拒绝规则:每个被接受的前缀,连同重采样或奖励词元,其分布都恰如从目标 p 采样而来。
A 上下文 D 草稿:提出 gamma 个词元 A->D V 目标:一次传播给所有位置打分 D->V R 在 p 比 q 下接受? V->R O 发出被接受的词元 R->O 接受一段 C 从残差 p 减 q 重采样 R->C 首次拒绝 O->A C->O
图 33.3. 投机解码的循环:一个廉价的草稿提出一段词元,一次目标传播给它们全部打分,一条修正过的拒绝规则保留最长的有效前缀,同时保持目标的分布。据 Leviathan 等(2023)与 Chen 等(2023)。

图 33.3 画出了这条循环。它所展示的那一串接受/拒绝决策是最简单的情形,即一条单一的线性续写。下文的自草稿方法用一棵树取代了那条线。

寻找猜测的来源

这些方法可以看成一场关于「猜测从何而来」的搜索:从一个独立的模型,向目标自身的部件移动,最终进入目标如何被训练。

第二个、更小的模型

第一个答案是第二个、更小的模型。Leviathan 等与 Chen 等都用了一个与目标同族的现成草稿模型,例如一个小 Chinchilla 为一个 70B 的 Chinchilla 打草稿 (Chen et al. 2023)。这无需改动目标,且可证明无损,但它要训练、托管并对齐第二个模型,而一个匹配不佳的草稿接受率很低。

目标模型自身的草稿头

Medusa (Cai et al. 2024) 去掉了那个独立模型。它不用草稿网络,而是在目标的最后一层隐藏状态上接入若干轻量解码头,每个头并行预测一个更远的未来词元。这些头产出的候选构成一棵树,而一个树状结构的注意力掩码让目标能在一次传播里验证那棵树的许多分支,而非一条单一的线性续写。Medusa 的头彼此独立地预测各个未来词元,这就限制了一个多词元猜测能有多连贯。它还提供了一种典型接受(typical-acceptance)方案,为换取更多速度而放松精确采样,所以处于该模式的 Medusa 是刻意不保持分布的,与投机解码的精确性是另一笔交易 (Cai et al. 2024)。

Hydra (Ankner et al. 2024) 修正了这个独立性的局限。它的草稿头是顺序依赖的:预测第三个词元的头能看到第二个头提出了什么,于是多词元猜测在内部是连贯的,接受率随之上升。EAGLE 系列在「草稿应预测什么」上推得更远。EAGLE (Li et al. 2024) 观察到,在特征层级,即倒数第二层的隐藏状态上,自回归比在词元层级上更有规律,于是它通过预测下一个特征、再把它映射到一个词元来打草稿,并通过喂入已经领先一步采样出的词元来化解不确定性。EAGLE-2 (Li et al. 2024) 让验证树变成动态的:因为一个草稿词元的接受与否取决于上下文而不只取决于其位置,它在草稿自信处展开草稿树、在不自信处剪枝。EAGLE-3 (Li et al. 2025) 放弃了特征预测,转而在低、中、高层的融合之上做直接的词元预测,用作者称为训练期测试(training-time test)的流程训练,这让草稿器能随其训练数据增长而持续改进。

无草稿分支

一条平行的支线则彻底去掉了草稿。前瞻解码 (Fu et al. 2024) 把自回归生成重述为用 Jacobi 迭代(一种不动点迭代,一次同时更新一整窗的未来位置)求解一个非线性系统,并沿途收集该迭代产出的 n-gram。一条验证分支随后在同一步里把那些 n-gram 与目标核对。没有草稿模型,也没有额外训练的头;并行性来自该问题的不动点结构,而该方法是精确的。

猜测还可以是检索来的,而不必是算出来的。提示词查找解码把生成末尾的几个词元与提示词做匹配,把当初跟在后面的那段 n-gram 提出来作草稿,完全不动用模型 (Saxena 2023)。它已是 vLLM 与 TensorRT-LLM 里的标准投机方法之一,在输出大量复用输入的场景,检索增强的回答、编辑、代码,效果最强。

把猜测训练进去

最后一步把猜测折进了训练。多词元预测 (Gloeckle et al. 2024) 用若干共享主干的输出头训练基座模型,使每个位置一次预测后续 nn 个词元。作者发现这作为辅助目标能提升样本效率,而关键在于,那些额外的头在推断时兼作内建的草稿器。DeepSeek-V3 (DeepSeek-AI 2024) 把这带进了一个前沿系统:它的 MTP 模块与主模型一同训练,随后被复用于投机解码,据报告它的第二个预测词元有 80% 到 90% 的时间被接受,并把生成吞吐量提高约 1.8 倍。

S 独立草稿模型 Leviathan, Chen H 自草稿头 Medusa, Hydra S->H J 无草稿的 Jacobi 迭代 lookahead S->J E 特征与词元打草稿 EAGLE 1/2/3 H->E M 把草稿训练进去 多词元预测, DeepSeek-V3 H->M E->M
图 33.4. 猜测从何而来:方法从一个独立的草稿模型,移向目标自身的部件,最终进入目标如何被训练,旁边还分出一条无草稿的支线。

图 33.4 描出了这场搜索。

加速何时成立

这里的每一种方法,都用更多的并行算力与更多用于验证的内存流量,换取更少的顺序步数。边界,就在那笔交易不再划算之处,而其中最清楚的一条,是由服务场景而非方法本身所设定的。

图 33.5 展示了为何同一种方法可以提升性能,也可能降低吞吐。在小批大小下,加速器的计算单元空等权重而闲置,于是投机为验证候选所花的 FLOPs 原本也没有被充分利用。在大批大小下,权重被摊到许多序列上,计算单元本已饱和,于是验证那些随后被拒绝的词元会与真正的工作争抢 FLOPs,反而可能降低总吞吐。整章的前提,即解码是内存受限的,只在小批大小这个场景中成立。

cluster_L 小批:内存受限 cluster_R 大批:算力受限 L1 计算单元闲置,空等权重 L2 有富余的 FLOPs L1->L2 L3 用富余算力验证候选 L2->L3 L4 更少的顺序步数,投机胜出 L3->L4 R1 权重被摊到许多序列上 R2 计算单元饱和 R1->R2 R3 被拒绝的词元仍消耗 FLOPs R2->R3 R4 验证与真正的工作争抢,可能落败 R3->R4
图 33.5. 为何一个加速数字是某种服务场景的属性。在小批大小下,计算单元在内存上空等,于是投机额外的 FLOPs 来自富余算力。在大批大小下,计算单元饱和,于是验证被拒绝的词元会争抢 FLOPs,反而可能耗损吞吐。

这笔交易下面还有另外三项取舍,值得逐一点出,因为它们解释了这条谱系为何这样一路演进。

  • 接受率与草稿成本。 一个更大或训练得更好的草稿器会提高接受率,但每次提议的成本也更高。最优草稿,是其接受率高到所省下的目标传播能盖过草稿自身成本的、那个最便宜的草稿。这正是自草稿头与特征层级打草稿胜出的原因:它们成本很低,却又与目标对齐。图 33.6 画出了这所蕴含的最优点:随着草稿变长,经成本调整的加速先升、到顶、再落,因为过了某个长度,额外的验证工作就盖过了它节省的词元,而一个更便宜的草稿器会把那个顶点推向更长的草稿。
  • 树宽与浪费。 验证一棵更宽的候选树,每次传播能接受更多词元,但会在终将被拒绝的分支上消耗算力。动态树,如 EAGLE-2 中的,正是为了只在草稿自信处使用那份宽度而存在。
2026-06-21T23:29:51.364689 image/svg+xml Matplotlib v3.11.0, https://matplotlib.org/ 0.0 2.5 5.0 7.5 10.0 12.5 15.0 17.5 20.0 草稿长度 gamma(每次提出的词元数) 0.0 0.5 1.0 1.5 2.0 2.5 3.0 3.5 成本校正后的加速比 接受率 alpha = 0.8 草稿成本比 c = 0.02 草稿成本比 c = 0.05 草稿成本比 c = 0.1
图 33.6. 接受率与草稿成本之间取舍的示意图:经成本调整的加速随草稿长度变化,接受率固定,并给出若干草稿对目标的成本比。每条曲线都在某个最优草稿长度处见顶,而一个更便宜的草稿器会把顶点向右移。据 Leviathan 等(2023)与 Chen 等(2023)。
  • 无损与有损。 投机解码、前瞻解码与 EAGLE 系列精确地保持目标的输出分布。Medusa 的典型接受模式用那份精确性换速度。多词元预测改变的是训练,而非采样保证。一条有损捷径是否可接受,是一个应用决策,并不是服务系统天然得到的收益。
争议所在

这一文献中所报告的加速,原始投机解码的 2 到 3 倍、EAGLE-2 (Li et al. 2024) 的 3 到 4 倍、EAGLE-3 (Li et al. 2025) 的更大数字,都是在小批大小下测得的,那时服务是延迟受限的,加速器的算力确实在闲置。它们在论文之间并不可比,因为每篇用的基线、硬件与任务都不同,它们也不会迁移到每一种部署。随着批大小增长,服务器会从内存受限变为算力受限:投机原本使用的闲置 FLOPs 不再富余,而验证那些随后被拒绝的词元反会降低总吞吐。投机解码在高吞吐的生产服务中是否划算,如今有了运维上的答案:对自带训练好草稿器的模型,它已是生产默认,SGLang 报告在开启 MTP 的情况下,DeepSeek-V3 的输出吞吐最高提高 60% (Eigen AI Team and SGLang Team 2025);引擎还会随批大小缩短草稿,在高并发下缩到零。于是这条场景边界从一个开放问题变成了一条调度策略。仍然悬而未决的,是这个切换点该定在哪里,以及独立草稿、自草稿与无草稿三种设计之间的取舍,它们以不同的方式权衡托管成本、训练成本与接受率,尚无定论。把任何单一的加速数字都当作某种服务场景的属性,而非该方法本身的属性。

下层约束

整章都说明了一个下层约束如何决定算法形状。第 31 章第 32 章 描述的内存带宽瓶颈,即单流解码每个词元都重新载入每个权重、让计算单元闲置,正是「花并行算力去省顺序步数」一开始就值得的原因。倘若解码是算力受限的,就没有闲置的 FLOPs 可用,这些方法也都帮不上忙。解码算法的形状,是由它之下那块芯片的带宽对算力之比所设定的。

验证这一步的内部

值得具体看的是验证这一步,因为正确性就住在那里。给定来自 qq 的草稿词元 x1,,xγx_1, \dots, x_\gamma,以及来自一次并行传播的目标分布 p1,,pγp_1, \dots, p_{\gamma},这里下标按草稿位置编号,γ\gamma 是草稿长度。接受循环很短:

for i in range(gamma):
    r = uniform(0, 1)
    if r < min(1, p[i][x[i]] / q[i][x[i]]):
        emit(x[i])              # 被接受,无需额外的目标步
    else:
        emit(sample(normalize(relu(p[i] - q[i]))))  # 修正词元
        break                   # 在首次拒绝处停止
# 若全部 gamma 个都被接受,从 p[gamma] 采样一个奖励词元

让它精确的两个细节是:拒绝时从残差 max(0,pq)\max(0, p - q) 重采样,以及在一段全接受之后的奖励词元;残差项表示目标分布相对草稿分布尚未覆盖的概率质量,两者合起来正是分布保持定理所要求的。对于自草稿与基于树的方法,同样的接受逻辑跑在一棵树而非一条线上:一个树注意力掩码让单次目标传播给每个分支打分,而穿过那棵树的最长被接受路径被输出。图 33.7 展示了这为何胜过线性草稿。一条线性草稿只提出一种续写,于是一次早早的拒绝就浪费掉它之后的一切。一棵树则在每个位置上覆盖若干续写,树注意力掩码几乎以一次的代价在同一次目标传播里给它们全部打分。目标随后输出每个词元都被接受的那条最长路径。

ctx 上下文 a1 这只 ctx->a1 a2 一只 ctx->a2 b1 a1->b1 b2 a1->b2 b3 a2->b3 c1 坐下 b1->c1 c2 跑开 b1->c2 c3 吠叫 b2->c3
图 33.7. 树状的打草稿与验证。从上下文出发,草稿头在每个位置提出若干候选词元,而非一个。一个树注意力掩码在单次目标传播里给每个分支打分,最长的完全被接受的路径(加粗)被输出。据 Cai 等(2024)与 Li 等(2024)。

在运维上,服务栈把这暴露为一个草稿器的选择。一个独立草稿模型是要载入并调度的第二个检查点。EAGLE 式与 Medusa 式的草稿器,是针对一个冻结目标训练、并与之并排载入的小头模块。如 DeepSeek-V3 那样的多词元预测打草稿,则根本不需要单独的产物,因为那些头已被训练进了模型。实际的失效模式,是草稿器对该工作负载的接受率太低,到那时投机不是削减延迟,反而在增加延迟。正因如此,生产中要盯的指标是接受率,而不是某篇论文里醒目的加速数字。

延伸阅读

  • Leviathan et al., “Fast Inference from Transformers via Speculative Decoding,” 2023. arXiv:2211.17192
    推测解码用一个小型草稿模型提出词元、再由大目标模型并行校验,在不改变输出分布的前提下实现 2X-3X 加速。
  • Chen et al., “Accelerating Large Language Model Decoding with Speculative Sampling,” 2023. arXiv:2302.01318
    推测采样利用小草稿模型生成候选词元,再由大目标模型并行验证,在 Chinchilla 上实现 2–2.5 倍推测解码加速,且不改变输出分布。
  • Cai et al., “Medusa: Simple LLM Inference Acceleration Framework with Multiple Decoding Heads,” 2024. arXiv:2401.10774
    MEDUSA 通过在 LLM 上附加多个额外解码头并结合基于树的注意力机制,在每步并行预测并验证多个词元,无需独立草稿模型即可实现 2.2-2.8 倍推测解码加速。
  • Ankner et al., “Hydra: Sequentially-Dependent Draft Heads for Medusa Decoding,” 2024. arXiv:2402.05109
    Hydra heads 是一种序列相关的草稿头,用于推测解码,通过将每次预测条件化于先前候选词元,相比自回归解码最高提升 2.70 倍吞吐量。
  • Li et al., “EAGLE: Speculative Sampling Requires Rethinking Feature Uncertainty,” 2024. arXiv:2401.15077
    EAGLE 是一种推测解码框架,通过以超前一步的词元序列为条件预测次顶层特征,在保持输出分布不变的情况下实现对自回归 LLM 解码 2.7x-3.5x 的延迟加速。
  • Li et al., “EAGLE-2: Faster Inference of Language Models with Dynamic Draft Trees,” 2024. arXiv:2406.16858
    EAGLE-2 将推测解码中的静态草稿树替换为上下文感知的动态草稿树,无需额外训练即可实现 3.05x-4.26x 的无损 LLM 推理加速。
  • Li et al., “EAGLE-3: Scaling up Inference Acceleration of Large Language Models via Training-Time Test,” 2025. arXiv:2503.01840
    EAGLE-3 用直接词元预测和多层特征融合替代特征预测,通过 training-time test 技术发现推测解码的扩展律,推理加速比最高达 6.5x。
  • Fu et al., “Break the Sequential Dependency of LLM Inference Using Lookahead Decoding,” 2024. arXiv:2402.02057
    Lookahead Decoding 无需草稿模型,通过 Jacobi 迭代并行生成并验证 n-gram,将大语言模型自回归解码速度提升最高 4 倍。
  • Gloeckle et al., “Better & Faster Large Language Models via Multi-token Prediction,” 2024. arXiv:2404.19737
    通过让大语言模型使用 n 个独立输出头同时预测多个未来词元,可提升样本效率、在代码基准上提升约 15
  • DeepSeek-AI, “DeepSeek-V3 Technical Report” (multi-token prediction reused for speculative decoding), 2024. arXiv:2412.19437
  • Eigen AI Team and SGLang Team, “Accelerating SGLang with Multiple Token Prediction,” 2025. lmsys.org
    SGLang 为 DeepSeek-V3 实现的多词元预测投机解码,据报告在小规模部署中把输出吞吐最高提高 60
  • Saxena, “Prompt Lookup Decoding,” 2023. github.com
    提示词查找解码用对提示词的 n-gram 匹配取代投机解码中的草稿模型,在输出大量复用输入的任务上带来 2 至 4 倍加速且不改变输出质量;已进入 transformers 与 vLLM。

评论

登录后评论