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

更快的解码

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

前两章分别讨论了请求时序与内存分配,也确立了一条执行规则:执行词元计划之前,必须先预留所需状态。更快的解码改变的是这个计划。目标模型不再每次只生成一个新词元,而是由候选生成器先给出多个候选,目标模型再一次为它们打分。一轮成功的验证可以返回多个词元,但候选生成、验证计算和临时 KV 状态也都会产生开销。

当目标模型解码时没有充分利用加速器,这种交换可能很划算。低批量的稠密模型解码常受权重搬运限制,便是典型场景。但这不是解码的普遍属性。长上下文会增加 KV 流量,模型并行会增加通信,更大的批量还可能使验证转为算力受限。因此,推测方法是否划算,必须放到实测的服务运行区间中判断。

2023 年的两项工作给出了这种思路的精确版本:Leviathan、Kalman 与 Matias 提出的推测解码 (Leviathan et al. 2023),以及 Chen 等人提出的推测采样 (Chen et al. 2023)。后续工作改变了候选的来源与组织方式。Medusa 与 Hydra 增加草稿头 (Cai et al. 2024; Ankner et al. 2024),EAGLE 系列学习特征或词元草稿器 (Li et al. 2024; Li et al. 2024; Li et al. 2025),前瞻解码通过迭代构造候选 (Fu et al. 2024),多词元预测则在训练时加入未来词元模块 (Gloeckle et al. 2024)。这些是设计选择,并不是一条必须依次经过的技术谱系。

生成虽有顺序依赖,验证可以并行

自回归生成仍有顺序依赖:第 i+1i+1 个词元取决于第 ii 个词元。候选后缀预先提供了这些依赖所需的输入。目标模型采用因果掩码后,便能在一次前向传播中并行给后缀中的每个位置打分。最终决定权仍在目标模型手中,候选只是创造了一批可以验证的工作。

设线性候选的长度为 γ\gamma。用 AkA_k 表示这样一个事件:前面所有位置都已接受,并且草稿的第 kk 个位置也被接受。定义

sk=Pr(A1Ak),s0=1.s_k=\Pr(A_1\cap\cdots\cap A_k),\qquad s_0=1.

如果每轮输出已接受的前缀,再加一个修正词元或奖励词元,并且没有停止条件提前截断输出,那么该轮产出的词元数 YY 满足

E[Y]=1+k=1γsk.\mathbb E[Y]=1+\sum_{k=1}^{\gamma}s_k.

这个式子说明,总体接受词元比例不能决定前缀存活率。较早的位置可能更容易通过,较晚的位置可能更难,接受事件之间也可能相关。只有额外假设每个位置的条件接受概率都恒为 α\alpha,才有 sk=αks_k=\alpha^k,从而得到

E[Y]=k=0γαk=1αγ+11α,α1,\mathbb E[Y] =\sum_{k=0}^{\gamma}\alpha^k =\frac{1-\alpha^{\gamma+1}}{1-\alpha}, \qquad \alpha\ne1,

这里,当 α=1\alpha=1 时,E[Y]=γ+1\mathbb E[Y]=\gamma+1。这个量表示每轮验证的期望产出词元数,不是延迟加速比。它还没有计入这一轮花费的时间与内存。

下面的可运行示例用一组不相同的条件接受概率计算前缀存活率,再与使用这些概率算术平均值所得的独立同分布估计比较。即使在这个很小的确定性示例中,两者也不相同。

conditional = [0.85, 0.75, 0.60, 0.40]

survival = []
alive = 1.0
for probability in conditional:
    alive *= probability
    survival.append(alive)

expected = 1.0 + sum(survival)
alpha = sum(conditional) / len(conditional)
iid_estimate = sum(alpha**k for k in range(len(conditional) + 1))

print("survival by position:", ", ".join(f"{value:.4f}" for value in survival))
print(f"expected tokens/cycle: {expected:.4f}")
print(f"iid estimate at alpha={alpha:.2f}: {iid_estimate:.4f}")

修正拒绝采样保持目标分布不变

推测解码(speculative decoding)是一种“提出候选、再验证候选”的方法,它通过修正规则保持目标模型的输出分布不变。先考虑应用既定解码策略后的一个位置,这套策略包括温度、logit 约束,以及任何 top-kk 或 top-pp 截断。这里,pp 表示目标分布,qq 表示候选分布,V\mathcal V 表示两者共同的词元空间。从 qq 中采样得到候选 XX,即 XqX\sim q,并以如下概率接受词元 vv

a(v)=min ⁣(1,p(v)q(v)).a(v)=\min\!\left(1,\frac{p(v)}{q(v)}\right).

候选既然能从 qq 中采到,必有 q(v)>0q(v)>0,因此分母有定义。若拒绝该候选,则从下面的残差分布采样:

Z=uV[p(u)q(u)]+,r(v)=[p(v)q(v)]+Z,Z=\sum_{u\in\mathcal V}[p(u)-q(u)]_+, \qquad r(v)=\frac{[p(v)-q(v)]_+}{Z},

其中 [z]+=max(0,z)[z]_+=\max(0,z)。拒绝概率就是 ZZ。对任意词元 vv,接受与修正两条路径贡献的概率质量为

q(v)a(v)+Zr(v)=min(p(v),q(v))+[p(v)q(v)]+=p(v).q(v)a(v)+Zr(v)=\min(p(v),q(v))+[p(v)-q(v)]_+=p(v).

Z=0Z=0,拒绝概率为零,残差分布也永远不会被采样。这个单位置恒等式会从左到右应用:遇到第一次拒绝便停止,输出一个修正词元,并丢弃剩余候选。如果 γ\gamma 个候选全部接受,则从目标模型在下一个位置的分布中再采样一个奖励词元。因此,目标模型的这次传播必须同时给出所有候选位置以及奖励位置的分布 (Leviathan et al. 2023; Chen et al. 2023)。

从 q 中采样候选词元,并保留每个位置上的候选概率。
目标模型带着候选后缀执行一次,为每个候选位置及可能的奖励位置给出 p。
每到一个位置,都以 min(1, p(v)/q(v)) 的概率接受候选。
第一次拒绝时,从 p − q 的正值部分归一化后采样一个词元,并停止继续核验。
若整个后缀都通过,则从目标模型在奖励位置的分布中再采样一个词元。
只保留已接受候选前缀对应的目标 KV;下一轮开始前回收被拒绝候选的状态。
图 33.1. 精确的线性推测采样周期。候选生成、目标打分、随机修正与状态提交是四项彼此分开的操作。

这里的“精确”是指输出分布相同,并不等于在同一随机种子下得到完全相同的词元序列。浮点内核、批处理方式和随机数消耗顺序都可能改变某次具体采样。要保持精确,比较的分布还必须采用相同的采样变换与停止策略;温度、截断、约束与词元映射不能暗中不同。EOS、停止序列和最大长度都可能缩短一轮执行,并使奖励词元不再产生。

贪心验证是另一套确定性契约。它可以接受与目标模型贪心词元一致的最长前缀,再采用目标模型在第一个不一致位置给出的词元。典型接受等放宽规则则有意牺牲分布相等性,换取其他质量或速度指标。系统必须把这些契约分开标明。

候选来源、候选结构与接受策略是三项独立选择

实现需要分别回答三个问题:候选由谁提出,候选如何组织,以及哪条规则允许提交输出。某种候选生成机制本身并不能保证采样精确。

候选来源 新增产物或状态 常见候选形状 重要条件
独立自回归模型 (Leviathan et al. 2023; Chen et al. 2023) 草稿权重、草稿 KV 与草稿调度 线性后缀 目标模型与草稿模型需要兼容的词元空间和采样概率。
附加草稿头 (Cai et al. 2024; Ankner et al. 2024) 学习得到的预测头;Hydra 让后续预测头以前面的候选为条件 线性或树形 训练与接受方案共同决定结果是精确采样、贪心一致还是放宽接受。
特征或词元草稿器 (Li et al. 2024; Li et al. 2024; Li et al. 2025) 与目标模型并列的学习模块 线性或动态树 仍由目标验证决定哪些候选词元可以提交。
提示词查找 (Saxena 2023) 针对提示词与输出中重复片段的索引或搜索 一个或多个检索后缀 只有工作负载包含可利用的重复时才有帮助,正确性仍由验证规则保证。
前瞻解码 (Fu et al. 2024) Jacobi 窗口、n-gram 池与定制掩码 多个 n-gram 续写 它去掉了学习式草稿器,但没有消除候选计算或临时状态。
多词元预测模块 (Gloeckle et al. 2024; DeepSeek-AI 2024) 与基座模型共同训练的未来词元预测头 线性或分支候选 训练目标只负责产生候选,并不是接受正确性的定理。

这张表不是排名。有的部署已经拥有兼容的小模型,有的模型则自带可用的预测头。候选质量也会随领域、上下文长度、采样设置和量化方式而变化。真正便宜的候选方案,是能在实际工作负载中降低目标周期实测成本的方案。

线性链与候选树消耗工作的方式不同

线性后缀包含 γ\gamma 个候选位置。如果较早的词元被拒绝,后面的词元在该轮就不可能输出。候选树通过同时保留多种续写来分散这种风险。树注意力掩码把各分支装入一次目标执行,同时保证每个节点只能关注自己的祖先节点。

flowchart TD
  C[上下文] --> A1[A1] --> A2[A2]
  C --> B1[B1] --> B2[B2]
  B1 --> B3[B3]
图 33.2. 候选树在每一层保留多种备选续写,线性后缀则每层只有一个节点。每个被打分的节点都会消耗验证计算与临时状态;最终可以提交哪条路径,由验证策略而不是掩码决定。

树注意力掩码只是让联合打分成为可能,并不会自动让验证器保持精确。贪心树搜索、保持分布的树采样和放宽接受的树验证,是不同的算法。增加树宽可能提高找到可用路径的机会,但验证耗时与临时 KV 会随被打分的节点数增加。被拒绝的分支同样是真实开销,不是免费的备选项。

加速必须用实际耗时衡量

加速是实际耗时的测量结果,不能从接受率或一轮产出的词元数直接推得。

t1t_1 为基线目标模型执行一个普通解码步的实测时间,tpropose(γ)t_{\mathrm{propose}}(\gamma) 为候选生成时间,tverify(γ,m)t_{\mathrm{verify}}(\gamma,m) 为目标模型验证含 mm 个候选节点的方案所需时间,treconcilet_{\mathrm{reconcile}} 为接受判断、同步和状态对账所需时间。对线性链而言,m=γm=\gamma。一个实用的一阶延迟比为

SlatencyE[Y]t1tpropose(γ)+tverify(γ,m)+treconcile.S_{\mathrm{latency}} \approx \frac{\mathbb E[Y]t_1} {t_{\mathrm{propose}}(\gamma) +t_{\mathrm{verify}}(\gamma,m) +t_{\mathrm{reconcile}}}.

分母就是 tcyclet_{\mathrm{cycle}}。换句话说,只有满足

tcycleE[Y]<t1.\frac{t_{\mathrm{cycle}}}{\mathbb E[Y]}<t_1.

推测方法才能降低平均每个输出词元耗时。验证时间会随候选位置、树节点、上下文长度、KV 流量、批次组成、内核和通信而变化。在低批量、受权重带宽限制的运行区间中,这部分增长可能足够小,从而让减少目标同步次数取得净收益。利用率更高时,被拒绝的候选工作会与其他请求争用资源。进入算力受限区间通常会缩小优势,但也不能由此断言所有候选方案必然失败;候选生成放在哪里、能否重叠、内核如何实现以及同步方式都会改变结果。

论文结果只能证明相应实验配置下可行,不能提供可迁移的固定倍数。Leviathan 等人在其 T5 实验中报告了约 2 到 3 倍的提升 (Leviathan et al. 2023),EAGLE 则在所评估的 LLaMA2-Chat 配置上报告了 2.7 到 3.5 倍的延迟下降 (Li et al. 2024)。两者使用的模型、硬件、软件、采样设置和基线均不相同。应先复现实验配置后再比较。

调度器必须规划推测工作

第 32 章的“预留、执行、提交”协议可以直接应用于这里。每轮开始前,调度器应为候选位置和工作区预留空间。线性方案需要容纳整个候选后缀,树形方案则需要容纳所有待打分节点。接纳时必须按计划中的最大值接纳,不能按期望接受长度接纳。

验证结束后,只能提交已接受草稿前缀对应的目标 KV,并释放所有被拒绝的尾部或分支。草稿缓存与目标缓存属于不同命名空间:它们来自不同模型或模块,张量不可互换。修正词元或奖励词元会成为下一轮目标执行的输入,届时才为它生成对应的目标 KV。调度器还必须在取消或失败时回滚预留,之后才能把同一批块交给其他请求。

不同请求接受的前缀长度不同,因此下一批工作是不齐整的。调度器重新装配批次时,必须保留每个请求的位置、掩码、停止状态与缓存所有权。内存压力增大或并发上升时,可以缩短 γ\gamma、收窄候选树、改用成本更低的候选生成器,或者退回普通的单词元解码。没有一个通用的批量阈值能替所有部署做出这些选择。

根据工作负载证据做选择

部署决策从契约开始,以负载测试结束。

  1. 固定输出契约。 明确服务承诺的是精确采样、与贪心序列逐词元一致,还是有文档说明的放宽规则。核对目标模型、词元器、词表映射、模型版本、适配器、采样变换、约束和停止行为。这里的采样变换包括 top-kk 与 top-pp
  2. 分析候选预算。 在有代表性的上下文长度、输出类型、批次形状和采样设置上,扫描线性链长度或树节点预算。必须纳入低接受率工作负载,不能只针对最容易的提示词调优。
  3. 测量完整周期。 记录被接受前缀长度的分布,以及候选、验证、接受、修正和奖励词元数;同时测量每个输出词元对应的目标周期数、候选生成时间、验证时间、状态对账时间,以及临时 KV 与工作区的峰值占用。
  4. 按服务系统评估。 在相同的接纳负载下比较,并报告 TTFT、TPOT、词元间延迟、端到端延迟、输出吞吐、有效吞吐、拒绝率、成本与能耗。中位数和尾部都要检查。
  5. 保留回退路径。 当预测成本高于普通解码、无法预留容量或兼容性检查失败时,关闭推测执行。记录每次回退发生的时间与原因。

同一个接受率或论文加速数字都不能回答部署是否受益。例如,两个系统可能接受相同比例的候选,却在不同位置发生拒绝,因此得到不同的 E[Y]\mathbb E[Y]。它们也可能有相同的产出,但目标验证时间相差很大。

正确性与故障测试

先分别测试采样器和内存协议,再把两者放在一起测试。

  • 在一个很小的词表上,分别针对 p=qp=q、部分重叠和不相交支持集,将经验输出频率与目标分布比较。这里的部分重叠,是指候选分布只有一部分概率质量与目标分布重合。强制制造第一次即拒绝、较晚位置拒绝和全部接受三种情况。
  • 将贪心输出与基线解码逐词元比较。测试 EOS、停止序列与最大长度,也要覆盖恰好在边界处全部接受的情况。
  • 在不同温度、top-kk、top-pp、语法约束和 logit 处理器下重复测试。若词元器、适配器或约束不匹配,必须在开始执行前拒绝请求。
  • 把混合不同的已接受前缀长度的请求组成批次。重新装配批次后,验证位置、掩码、输出顺序和每个请求各自的随机状态。
  • 跨越缓存块边界,拒绝一棵较宽的候选树,在验证期间取消请求,并注入目标模型故障。核对每项预留、已提交块、引用计数和被释放分支。
  • 在不同批次与内核配置下,按明确给出的容差比较数值分布。不得要求随机采样逐位完全相同。
  • 把接受率压低并提高内存压力,确认排队时间有界,并能干净地退回普通解码。
争议所在

不存在普遍最优的候选来源、树形结构、草稿长度或批量阈值。精确随机采样、精确贪心序列与容许质量变化的接受规则,也代表不同的产品契约。若不同时给出目标模型与草稿模型、硬件、并行方式、批量、上下文、采样策略、基线和负载,跨论文的加速数字就无法比较。真正尚待回答的运维问题,不是推测方法能否生效,而是它的完整周期在某个具体服务中何时优于普通解码。

下层约束

更快的解码能让部分目标周期返回更多有用词元,同时也会扩大调度器的临时词元计划。它可以与连续批处理、分页 KV 分配、前缀复用和分离式服务组合,但前提是这些机制的预留与所有权规则都覆盖推测状态。批处理或内存策略一旦变化,延迟不等式也会变化,因此必须重新分析组合后的系统,不能把彼此独立测得的加速倍数直接相乘。

收益与边界

候选生成与验证并没有消除自回归。它只是预先提供候选依赖,使目标模型能够并行验证多个位置,然后只提交明确接受契约授权的输出。收益是每个输出词元所需的昂贵目标周期更少;代价是候选生成、更宽的验证、临时内存和更复杂的状态对账。

下一章改变的是另一项互补的量。量化会减少表示模型状态所需的字节数,融合内核会减少单个周期内的数据搬运与启动开销。这些变化既可能改变基线时间,也可能影响候选接受情况。因此,更快的解码、量化与内核需要一起测量,不能把各自的加速倍数直接相乘。

延伸阅读

  • Leviathan et al., “Fast Inference from Transformers via Speculative Decoding,” 2023. proceedings.mlr.press
    推测解码使用更快的草稿模型和修正拒绝采样来减少目标模型调用,同时保持目标分布;论文报告的收益只对应其 T5 实验设置。
  • Chen et al., “Accelerating Large Language Model Decoding with Speculative Sampling,” 2023. arXiv:2302.01318
    推测采样用一次目标模型调用验证草稿模型生成的短序列,并以校正分布保持目标分布不变。
  • Cai et al., “Medusa: Simple LLM Inference Acceleration Framework with Multiple Decoding Heads,” 2024. proceedings.mlr.press
    Medusa 增加未来词元预测头和树形注意力来生成并验证多个候选;其精确配置与典型接受配置对应不同的输出契约。
  • Li et al., “EAGLE-3: Scaling up Inference Acceleration of Large Language Models via Training-Time Test,” 2025. proceedings.neurips.cc
    EAGLE-3 从目标模型的融合特征训练直接词元草稿器,并评估草稿器规模如何影响推测解码的延迟与吞吐。
  • Fu et al., “Break the Sequential Dependency of LLM Inference Using Lookahead Decoding,” 2024. proceedings.mlr.press
    前瞻解码使用 Jacobi 迭代和 n-gram 池来生成并验证多个续写,不需要学习型草稿模型。
  • Gloeckle et al., “Better & Faster Large Language Models via Multi-token Prediction,” 2024. proceedings.mlr.press
    多词元预测把多个未来词元预测头作为辅助训练目标;这些预测头也可以在自推测解码中提供候选。

评论

登录后评论