想象一家餐厅里,主厨正在为客人手写一份欢迎词。传统做法是写完一个字,端走一个,再写下一个——客人等得着急,主厨也累得够呛。后来主厨请来一位“帮厨”:帮厨先把可能的下几个字写在纸条上,主厨快速扫一眼,对的直接上,错的划掉重写。这样一来,原本一次只能端一个字,现在一次能端出好几个字。这,就是并行解码的智慧。它让大模型不再“一字一顿”地生成,而是在一个周期内同时推进多个 token,再用验证机制守住质量。

岗位关联

对 AI 从业者来说,并行解码是突破自回归生成瓶颈、降低推理延迟的关键技术,掌握它能帮你在大模型部署与推理优化中快速找到加速路径。

目录
  1. 可视化演示
  2. 自回归瓶颈
  3. 核心思路
  4. 草稿生成方式
  5. 质量评估
  6. 加速对比
  7. 适用场景
  8. AI 应用场景
  9. Python 演示
  10. 常见误区
  11. 面试题

可视化演示

对比自回归(AR)、非自回归(NAR)和迭代精化三种解码模式。切换模式查看不同解码策略如何生成token序列及其速度差异。

本节配有交互动效(进入视口后自动加载,约 3KB)。

自回归解码 (AR) 每步根据已生成token预测下一个token,严格串行 N步生成N个token,质量最高但速度最慢 P(y_t | y_1,...,y_{t-1}) 自回归是大模型标准生成方式

自回归瓶颈

餐厅主厨今天要为客人手写一张欢迎词。他坚持“写完一个字,端走一个字,再写下一个”,结果客人等到菜都凉了。这个场景,对应大模型最经典的生成方式:自回归。它像一位只会一字一顿说话的主厨,每一步都在等待上一步的结果。

在技术世界里,token 是模型处理文字的最小单位,可以粗略理解为“字”或“词”。自回归模型根据已有的序列预测下一个 token:先有 \(x_1\),才能算 \(x_2\);有了前两个,才有 \(x_3\)。这种串行依赖让每一步都成为上一步的“人质”,无法跳过,也无法同时进行。

更麻烦的是,每一步并不是“零成本”。模型要从显存里读取权重和 KV cache,完成一次前向计算,再写回新的状态。GPU 虽然算力强大,但大量时间花在数据搬运上;再加上只能一步步来,硬件利用率很低。因此自回归延迟是一个线性累加:生成 N 个 token 就要 N 次串行前向,延迟随序列长度直线上升。

主厨也发现了:问题不在“写字慢”,而在“只能写完一个再写下一个”。如果能让多个字同时被准备,再由他快速确认,速度就能上一个台阶。于是,并行解码登场。

Latency=∑t=1TΔtt\displaystyle \text{Latency} = \sum_{t=1}^{T} \Delta t_t
通俗理解:生成总耗时等于每一步耗时依次相加。步骤越多、单步越慢,总延迟越高。
  1. $T$ 为生成总 token 数目标序列越长,累加项越多,延迟越高。
    TT
  2. $\Delta t_t$ 为第 $t$ 步耗时包含权重读取、KV cache 访问和计算。
    Δtt=tread+tcompute\Delta t_t = t_{\text{read}} + t_{\text{compute}}
  3. 求和号体现串行累加所有步骤必须按顺序完成,不能像并行计算那样合并。
    ∑t=1T\sum_{t=1}^{T}

核心思路

主厨请来一位帮厨。帮厨先不拿主厨的锅,而是用一口小锅快速炒出好几道候选菜,全部摆在台面上。主厨只需瞄一眼,凡是对的菜直接上桌,不对的划掉重写。这个“先备菜、再验收”的流程,就是并行解码的核心框架。

并行解码通常分两方:草稿模型(draft model)和目标模型(target model)。草稿模型一般更小、更快,负责一次生成 k 个候选 token;目标模型是真正的高质量大模型,负责一次前向验证这批候选。在贪心解码下,目标模型会选出每个位置最可能的 token,如果和草稿一致,就接受;不一致,就换上目标模型的答案,并丢弃后面所有候选。

这一机制的关键不是“猜得准”,而是“验得住”。只要拒绝/接受规则与目标模型的分布一致,最终输出和标准自回归完全等价,不会“走样”。换句话说,草稿负责大胆假设,目标模型负责小心求证,两者配合才能既快又稳。

帮厨虽然会猜错,但主厨有最终决定权;猜对的越多,一次上桌的菜越多。接下来要看,帮厨用什么方式备菜,才能让主厨省力又省时。

\displaystyle \tilde x_{t+1}, \ldots, \tilde x_{t+k} \sim q(\cdot \mid x_{<t}),\quadx_{t+i}=\begin{cases}\tilde x_{t+i}, & \tilde x_{t+i} = \hat x_{t+i}\\\hat x_{t+i}, & \tilde x_{t+i} \ne \hat x_{t+i}\end{cases}
通俗理解:草稿模型先猜一串候选,目标模型再逐位核对;猜对了就用候选,猜错了就换成目标模型自己的答案。
  1. 草稿模型分布 $q$负责根据已有上下文批量生成候选 token,速度和成本通常低于目标模型。
    q(⋅∣x<t)q(\cdot \mid x_{<t})
  2. k 个候选 token一次生成未来 k 个位置,这是并行解码能“同时推进多个 token”的关键。
    x~t+1,…,x~t+k\tilde x_{t+1}, \ldots, \tilde x_{t+k}
  3. 目标模型的贪婪输出 $\hat x_{t+i}$目标模型在每个位置给出最可能的 token,作为验收基准。
    x^t+i=arg⁡max⁡p(⋅∣x<t+i)\hat x_{t+i} = \arg\max p(\cdot \mid x_{<t+i})
  4. 接受/修正规则候选等于目标答案则接受,否则修正为该位置的正确答案,并丢弃后续候选。
    xt+i={x~t+i,x~t+i=x^t+ix^t+i,x~t+i≠x^t+ix_{t+i}= \begin{cases} \tilde x_{t+i}, & \tilde x_{t+i} = \hat x_{t+i}\\ \hat x_{t+i}, & \tilde x_{t+i} \ne \hat x_{t+i} \end{cases}

草稿生成方式

帮厨有两种风格:一种是“小徒弟”,用自己的一套经验快速猜;另一种是“翻菜谱”,回忆以前做过的菜里最常见的搭配。它们对应并行解码中几种常见的草稿生成方式。

最直接的是用一个小模型当草稿模型。它和主模型结构相似,但参数量小、推理快,先输出 k 个候选 token,再用目标模型验证。另一种是 n-gram 回溯:从已经生成的上下文里,统计历史上出现过的短语,把最常见的高频后续词当作草稿。还有一种是在同一个大模型内部加几个“并行头”(如 Medusa),相当于主厨自己的快手分身,一起预测未来多个位置。

无论哪种方式,目标都是给出与目标模型尽量一致的候选序列。草稿分布 \(q\) 越接近目标分布 \(p\),接受率越高。工程上常把多种方式组合使用:小模型负责通用语义,n-gram 负责高频短语,并行头负责结构化的重复内容。

帮厨再能干,也不能替主厨做决定;草稿只是“提案”,最终的质量由验收环节把控。于是下一节,我们来看看如何评估草稿的质量。

x~t+1:t+k=Draft(x<t),Draft∈{小模型,n-gram,并行头}\displaystyle \tilde x_{t+1:t+k} = \text{Draft}(x_{<t}),\quad\text{Draft} \in \{\text{小模型}, \text{n-gram}, \text{并行头}\}
通俗理解:草稿来源可以多样,但本质都是“快速给出多个候选”,供后续验证。
  1. $\tilde x_{t+1t+k}$ 为草稿候选序列:表示从 t+1 到 t+k 连续 k 个位置的一次性提案。
    x~t+1:t+k\tilde x_{t+1:t+k}
  2. Draft 函数输入已有上下文,输出候选序列;这个函数可以是不同结构的模型或统计方法。
    Draft(x<t)\text{Draft}(x_{<t})
  3. 候选方案集合小模型、n-gram、并行头各有优缺点,可单独使用也可混合搭配。
    Draft∈{小模型,n-gram,并行头}\text{Draft} \in \{\text{小模型}, \text{n-gram}, \text{并行头}\}

质量评估

主厨准备了一本小账本,记下帮厨每次端来的 k 道菜里,有多少道一次过关。这个比例,就是并行解码里的“接受率”。

接受率 \(\alpha\) 是衡量草稿质量最直接的指标:一批 k 个候选 token 中,被目标模型接受的比例。若 \(\alpha\) 接近 1,说明草稿模型对目标模型的分布模拟得很好;若很低,说明草稿几乎全错,验证完还得重来。在采样模式下,还需要用修正的拒绝采样规则,保证生成分布和原模型一致。

除了接受率,还要关注“分布一致性”:并行解码不能为了提速而牺牲输出质量。贪心解码下,只要逐位与目标模型一致,结果就和自回归完全一致;采样解码下,则要按概率比例接受或拒绝候选,保证采样分布不变。

验收标准定下后,顾客关心的问题回到上菜速度:接受率高了,真的能快多少?

α=1k∑i=1k1[x~t+i=xt+i∗]\displaystyle \alpha = \frac{1}{k}\sum_{i=1}^{k} \mathbb{1}\left[\tilde x_{t+i} = x^*_{t+i}\right]
通俗理解:接受率就是“帮厨端来的 k 道菜里,多少道被主厨直接留下”。
  1. k 为每轮草稿数量分母固定为每轮候选总数,便于横向比较。
    kk
  2. 指示函数 $\mathbb{1}[\cdot]$括号内条件成立时取 1,否则取 0,用来统计单个 token 是否被接受。
    1[x~t+i=xt+i∗]\mathbb{1}\left[\tilde x_{t+i} = x^*_{t+i}\right]
  3. 目标真实 token $x^*_{t+i}$目标模型在对应位置给出的标准答案,是验收的“金标准”。
    xt+i∗x^*_{t+i}
  4. 求平均把所有位置通过情况加总后除以 k,得到一轮候选的平均接受率。
    1k∑i=1k\frac{1}{k}\sum_{i=1}^{k}

加速对比

假设主厨每轮验收 k 道菜,其中大部分一次通过,偶尔划掉一道。顾客等一桌菜的时间,就从“一道菜接一道菜”变成了“几道菜同时上”。这就是加速的来源。

理想情况下,如果所有候选都被接受(\(\alpha=1\)),一次前向就能生成 k 个 token,加速比接近 k。但实际中 \(\alpha<1\),每轮都会有候选被拒绝,需要目标模型修正,因此实际收益低于 k。把草稿生成的开销也算进去,真实加速比还要打折扣。

工程经验是:与其拼命把 k 调大,不如先提高接受率。一个小而准的草稿模型,往往比一个“大而乱”的草稿模型更划算。因为草稿的头一次错误会让整轮候选作废,接受率低时,额外生成的大量候选反而是负资产。

因此,并行解码不是万能药。到底什么时候用,得看餐厅的客流和灶台负荷。

Sideal≈kα+(1−α),Sreal=TautoTparallel\displaystyle S_{\text{ideal}} \approx k\alpha + (1-\alpha),\qquad S_{\text{real}} = \frac{T_{\text{auto}}}{T_{\text{parallel}}}
通俗理解:加速比约等于“每轮平均被接受的有效 token 数”。接受率越高,越接近草稿长度 k。
  1. k 为草稿长度一次并行生成的最大 token 数,也是加速比的理论上限。
    kk
  2. 接受率 $\alpha$决定草稿候选中有多少能直接被目标模型认可。
    α\alpha
  3. $(1-\alpha)$ 表示修正项每轮即使候选失败,也会产生一个目标模型生成的修正 token,因此算作被有效推进的一步。
    1−α1-\alpha
  4. 真实加速比用自回归总时间除以并行解码总时间,是所有开销综合后的最终结果。
    Sreal=TautoTparallelS_{\text{real}} = \frac{T_{\text{auto}}}{T_{\text{parallel}}}

适用场景

如果餐厅里只有一桌客人,主厨闲着,帮厨备菜就能明显提速;如果大堂坐满几百桌,灶台和主厨早已满负荷,帮厨反而会占用额外的灶眼,添乱。并行解码的适用场景,正像这客流高低。

技术上说,并行解码最适合“单条生成请求延迟敏感”的场景,例如聊天机器人、代码补全。这些场景 batch 小,GPU 算力富余,草稿模型可以利用空闲资源换延迟。反之,在大 batch 场景,算力和带宽已被充分利用,草稿模型反而增加额外开销。此外,草稿模型和目标模型的 tokenizer、采样参数必须一致,否则接受率会大跳水。

可以用一个粗略的收益条件判断:草稿模型生成 k 个 token 的成本 \(k c_q\) 加上目标模型一次验证成本 \(c_p\),必须小于目标模型直接生成 k 个 token 的成本 \(k c_p\)。经过化简,就得到下面的收益条件公式。

主厨最终明白了:工具没有绝对好坏,关键看是否匹配当前厨房的节奏。并行解码也一样,它让小 batch、低延迟的推理场景焕然一新,但在满负荷的大 batch 场景里需要谨慎选择。

kα>1+kcqcp\displaystyle k\alpha > 1 + \frac{k c_q}{c_p}
通俗理解:只有当每轮有效产出的 token 数超过“验证成本 + 草稿成本”时,并行解码才真正划算。
  1. $k\alpha$ 为每轮有效产出粗略表示一轮并行解码平均推进的真实 token 数。
    kαk\alpha
  2. 常数 1 代表目标模型一次验证无论候选对错,目标模型都要做一次前向。
    11
  3. $k c_q$ 为草稿总成本生成 k 个候选 token 的额外计算开销。
    kcqk c_q
  4. $c_p$ 为目标模型单次前向成本用于把草稿成本折算成目标模型前向的“等价次数”。
    kcqcp\frac{k c_q}{c_p}

AI 应用场景

在线对话机器人延迟优化

阶段:大模型推理加速

解决的问题:传统自回归解码在对话场景中一次生成一个 token,用户感到回答“一个字一个字往外蹦”,尤其在长回答中等待感很强。并行解码通过草稿模型批量生成候选、目标模型一次验证,能把推理延迟降低 2-4 倍。

具体案例:某客服机器人服务中的每个问题平均要生成 100 个 token,原来自回归需要 100 次串行前向。接入投机采样后,使用一个小参数草稿模型先生成 4 个候选,再由大模型验证,目标前向次数减少到约 30 次,用户感知延迟明显下降。

代码补全与交互式编程助手

阶段:生成优化与工程集成

解决的问题:代码补全对延迟极其敏感,用户每敲一个字符都希望立刻看到建议。自回归解码的串行等待让补全不跟手;并行解码可以在空闲算力充足的小 batch 请求下,一次预测多行 token 并快速验证。

具体案例:某 IDE 插件使用 n-gram 草稿生成常见的代码片段后缀,再由大模型验证。由于代码中重复结构和模板很多,草稿命中率高,接受率可达 0.6-0.8,补全响应时间从 800ms 降到 300ms。

Python 演示

python68 行
import random random.seed(42)TEXT = "我爱学习大模型并行解码加速推理"  class TargetModel:    """目标模型:每个候选位置都会给出真实 token"""     def __init__(self, text):        self.text = text        self.pos = 0        self.forward_calls = 0     def verify(self, candidates):        # 一次前向:验证一批候选,返回本轮真正生成的 token        self.forward_calls += 1        generated = []        for cand in candidates:            if self.pos >= len(self.text):                break            true_token = self.text[self.pos]            self.pos += 1            generated.append(true_token)            if cand != true_token:                break        return generated  class DraftModel:    """草稿模型:根据当前位置预测 k 个候选 token"""     def __init__(self, text, hit_rate):        self.text = text        self.hit_rate = hit_rate        self.calls = 0     def draft(self, pos, k):        self.calls += 1        if pos + k <= len(self.text) and random.random() < self.hit_rate:            return self.text[pos:pos + k]        return random.sample(self.text, k)  def autoregressive(target):    while target.pos < len(target.text):        candidates = [target.text[target.pos]]        target.verify(candidates)  def speculative(target, draft, k=3):    while target.pos < len(target.text):        pos = target.pos        candidates = draft.draft(pos, k)        target.verify(candidates)  target_ar = TargetModel(TEXT)autoregressive(target_ar) target_sp = TargetModel(TEXT)draft = DraftModel(TEXT, hit_rate=0.7)speculative(target_sp, draft, k=3) print("自回归解码目标前向次数:", target_ar.forward_calls)print("并行解码目标前向次数:", target_sp.forward_calls)print("草稿调用次数:", draft.calls)print("理想加速比:", round(target_ar.forward_calls / target_sp.forward_calls, 2))
目的:用一个小型模拟直观展示并行解码如何通过“草稿 + 验证”减少目标模型串行前向次数。
  1. TargetModel.verify(candidates)一次前向验证整批候选,并生成真实 token。
  2. DraftModel.draft(pos, k)按命中率生成 k 个候选,命中率可以理解成草稿质量。
  3. autoregressive(target)每轮只验证 1 个候选,代表自回归逐 token 生成。
  4. speculative(target, draft, k)每轮先批量生成候选,再交给目标模型一次验证。
  5. random.sample(self.text, k)模拟草稿模型“猜不准”的情况,随机抽取 token。
  6. target.pos += 1目标模型每接受或修正一次,就真正向前推进一个 token。

常见误区

误区并行解码一次生成好几个 token,肯定不如一个一个来稳,生成结果会“飘”甚至语法不通。

正解并行解码把“生成”拆成“草稿”和“验证”。草稿可以随便猜,但每个 token 都要经过目标模型逐位验收,验收规则与自回归一致。因此贪心解码结果与自回归完全一致,采样解码也可通过修正拒绝采样保持分布不变。质量不会因为批量提案而下降。

为何常见:容易把“草稿批量生成”误当成“最终结果批量生成”,忽略了中间的验证环节。

误区都是“并行”,所以并行解码就是同时处理多个用户的请求,等价于增大推理时的 batch size。

正解batch size 是同时处理多条独立序列;并行解码是在同一条序列内部同时推进多个 token。两者可以叠加:既做多请求批处理,又在每个请求内部做并行解码。

为何常见:“并行请求”和“并行 token 生成”都叫并行,但作用粒度完全不同。

误区草稿模型只是个“猜答案的”,猜错了反正会被大模型纠正,所以模型越小越省成本。

正解草稿模型太小,接受率会直线下降,每轮验证“大半是错”,目标模型还要重新生成,浪费更多时间。草稿模型的“准”比“小”更重要,关键是让草稿分布尽量接近目标分布。

为何常见:只看到小模型便宜,没看到验证驳回后带来的隐形成本。

误区一次能生成 k 个 token,所以速度就快 k 倍,k 越大越好。

正解加速比还要乘上接受率,并扣除草稿生成和目标模型验证的开销。理想上限可能是 k 倍,实际通常只有 2-4 倍;如果草稿过弱,甚至可能比自回归还慢。

为何常见:把理论理想当成现实,忽略了“拒绝重写”和“额外前向”带来的开销。

面试题

Q1. 自回归生成时,为什么大模型不能一次输出整个句子?

单选题 · easy

  • A.模型参数量太大无法一次性计算
  • B.每一步依赖上一步生成的 token← 正确答案
  • C.显存大小限制了输出长度
  • D.训练数据要求逐字预测

答案:B。自回归的“回归”体现在把上一步输出拼进输入,再预测下一步,因此天然存在串行依赖。参数量、显存、训练目标都不是“不能一次输出”的直接原因。

Q2. 并行解码最核心的框架可以概括为?

单选题 · easy

  • A.草稿生成 + 验证接受← 正确答案
  • B.模型剪枝 + 量化压缩
  • C.权重共享 + 低秩分解
  • D.动态 batch + 内存池

答案:A。并行解码的关键是先由草稿模型批量生成候选,再由目标模型验证和接受,其他选项属于模型压缩或调度优化,不是并行解码的框架核心。

Q3. 在贪心解码中,目标模型验证草稿候选时应该?

单选题 · easy

  • A.只要候选不在词典就拒绝
  • B.候选与目标模型贪婪输出一致则接受← 正确答案
  • C.候选长度必须大于 1 才接受
  • D.所有候选无条件接受

答案:B。贪心解码下,目标模型每个位置只认概率最大的 token。若草稿候选恰好等于该 token,就直接接受;否则用目标模型的输出修正,保证结果与自回归一致。

Q4. 接受率 \(\alpha\) 的定义是什么?

单选题 · mid

  • A.草稿模型大小与目标模型大小之比
  • B.一批候选 token 中被目标模型接受的比例← 正确答案
  • C.目标模型一次前向消耗的时间
  • D.模型生成 token 的总数

答案:B。接受率衡量草稿质量,是一轮草稿中通过验证的 token 数量占总候选数的比例。它直接决定并行解码的有效产出和加速收益。

Q5. 草稿模型使用 n-gram 方式生成候选的优点是什么?

单选题 · mid

  • A.不需要额外训练,直接从历史文本统计← 正确答案
  • B.一定比小模型草稿更准确
  • C.可以无限增加草稿长度
  • D.完全不受 tokenizer 影响

答案:A。n-gram 从已生成的上下文里统计高频短语,无需训练即可得到候选。它并不总是更准,也不能无限加长,而且同样受词表影响。

Q6. 如果草稿长度 k=4,接受率 \(\alpha=0.5\),理想加速比约为多少?

单选题 · mid

  • A.约 4 倍
  • B.约 3.5 倍
  • C.约 2.5 倍← 正确答案
  • D.约 1 倍

答案:C。按近似公式 \(S \approx k\alpha + (1-\alpha)\),代入 k=4、\(\alpha=0.5\),得到 \(2 + 0.5 = 2.5\) 倍。注意这还没考虑草稿开销。

Q7. 下面哪些方式可以产生草稿候选?

多选题 · mid

  • A.小模型在线预测← 正确答案
  • B.n-gram 从历史文本匹配← 正确答案
  • C.增大 beam search 宽度
  • D.在主干上增加轻量并行头← 正确答案

答案:ABD。小模型、n-gram、轻量并行头都是常见的草稿来源。beam search 是解码搜索策略,并不直接产生“未来多个位置的草稿候选”。

Q8. 为保证并行解码输出与自回归分布一致,需要注意哪些点?

多选题 · hard

  • A.草稿模型与目标模型的 tokenizer 一致← 正确答案
  • B.采样温度等参数一致← 正确答案
  • C.接受/拒绝规则满足分布修正← 正确答案
  • D.草稿模型必须比目标模型大

答案:ABC。tokenizer 和采样参数不一致会导致候选分布错位;采样模式下还要用修正拒绝采样保持分布。草稿模型大并非必要条件,反而更可能拖慢速度。

Q9. 某场景 batch 已接近 GPU 算力饱和,此时开启并行解码可能?

单选题 · hard

  • A.获得接近 k 倍加速
  • B.收益很小甚至变慢← 正确答案
  • C.必定降低生成质量
  • D.完全不起任何作用

答案:B。高 batch 下 GPU 已经满负荷,草稿模型会抢占算力,收益被额外开销抵消,甚至可能变慢。这时更适合考虑其他优化手段,并行解码收益有限。

Q10. 以下关于并行解码工程落地的说法正确的是?

多选题 · hard

  • A.草稿模型接受率越高,加速收益越明显← 正确答案
  • B.小 batch 延迟敏感场景更适合并行解码← 正确答案
  • C.大 batch 场景永远不会受益
  • D.草稿模型与目标模型需要共享词表← 正确答案

答案:ABD。接受率直接决定有效产出,小 batch 低延迟场景是并行解码的主场,共享词表能避免候选映射错位。但大 batch 在特定硬件和负载下仍可能受益,不能绝对化。