瓶颈在哪:串行生成与闲置的算力
大模型生成文本是自回归的:每一步只产出一个 token,而且下一个 token 依赖上一个,天生串行。更要命的是,每生成一个 token,都要把模型的全部权重从显存搬运一遍参与计算。以十亿参数量级以上的模型为例,一次前向里「搬数据」的开销远大于「做计算」的开销——瓶颈在显存带宽,不在算力。打个比方:GPU 像一家大餐厅的后厨,每来一张订单就要求把整本菜谱从库房搬出来翻一遍,翻完只炒一盘菜——厨师(算力)大部分时间在等菜谱到位。
一次前向只换一个 token,这是自回归解码最朴素的形态,也是最浪费的形态。投机解码(speculative decoding)的思路一句话就能说完:既然搬一次菜谱这么贵,能不能搬一次多炒几盘菜?
先猜后验
把生成拆成两步。第一步「猜」:用一个便宜的小模型(草稿模型)按常规方式快速连猜 k 个 token,比如 5 个。第二步「验」:把 k 个草稿 token 接到已有序列后面,交给目标大模型做一次前向传播。
这里用到了 Transformer 的一个基本性质:训练时序列是并行处理的——给定前缀,一次前向就能同时算出每个位置上「下一个 token」的分布。推理时之所以要串行,只是因为下一个位置的输入还不存在。现在草稿把「未来」补上了,大模型一次前向就能并行给出 k 个位置的验证结果。训练时的并行性,被反向借给了推理。
接受还是拒绝
拿到验证结果后,从前往后逐个检查草稿 token:每个位置上,草稿模型有自己的采样分布,目标模型也有。严格的算法用拒绝采样:对草稿选中的词 x,按概率比 min(1, p(x)/q(x)) 决定接受与否(p 是目标分布、q 是草稿分布);某个位置一旦被拒绝,它及其后面的草稿全部作废,并在该位置按目标模型的分布重新采样一个 token 兜底,本轮结束。
直觉上:草稿猜得准,一轮白赚多个 token;猜偏了,损失也有限——最坏情况是全被拒绝,退化为「大模型自己生成一个 token」,除了一点验证开销外没有额外代价。
为什么说是「无损」加速
关键性质:这套接受与拒绝机制在数学上保证,最终输出的 token 分布与目标模型自己逐个生成的分布完全一致。被接受的样本经过概率比修正,被拒绝的位置直接从目标分布重采样——无论草稿模型多差,输出都严格等价于目标模型的采样结果。这就是「免费加速」的底气:它改变的是计算的组织方式,不改变输出分布。这也是它和「降低精度换速度」一类优化最本质的区别——后者是近似,前者无损。
加速比从哪来
实际加速由两个因素决定。一是草稿接受率:草稿与目标模型分布越接近、任务越可预测,接受率越高。代码、模板化文本、结构化输出这类任务里,下一个 token 往往悬念不大,一次接受三五个 token 是常态,收益显著;高创造性的自由文本接受率就低。二是猜的长度 k:太短,验证开销占比高;太长,被拒绝的概率层层堆积,白猜的草稿反而拖后腿,需要按任务调。量级上,接受率理想时端到端能看到两到三倍加速,具体取决于草稿模型够不够小、够不够准。
变体一览
- 自草稿:不外挂小模型,让大模型「自己提前多猜几步」——在主干之外接几个额外的预测头,一次前向同时给出未来多个位置的候选。
- 树形投机:草稿不止猜一条链,而是展开成一棵候选树,目标模型一次前向并行验证整棵树,在「猜多长」与「猜多准」之间取得更灵活的权衡。
- n-gram 匹配:不训练任何模型,直接在当前上下文里找重复出现过的片段当草稿,对代码与模板类高度重复的文本意外地有效。
适用边界
投机解码不是万能的。第一,验证必须远比逐步生成便宜——这通常成立,因为验证只是一次并行前向;第二,草稿与目标分布差距太大时接受率崩塌,加速比滑向 1 甚至更低;第三,在高并发批处理的服务场景里,省下的带宽要与批处理本身填充算力的效率相权衡,是否划算看具体负载。挑对场景——单请求低延迟、输出可预测性高——它就是白捡的加速。
读者留言
COMMENTS 暂无还没有留言,来说第一句?