大模型文本生成采用标准自回归串行机制(Autoregressive Generation),存在结构性性能瓶颈,传统工程优化手段无法从根源上解决。下面用一个实际生成过程说明:用户输入“请解释注意力机制”,大模型只能逐 Token 输出回答。
flowchart TD
A[用户输入:请解释注意力机制] --> B[模型前向计算]
B --> C[生成第1个Token:注意力]
C --> D[拼接上下文:请解释注意力机制 注意力]
D --> B
B --> E[生成第2个Token:机制]
E --> F[拼接上下文:请解释注意力机制 注意力 机制]
F --> B
B --> G[生成第3个Token:是]
G --> H[继续循环生成下一个Token……]
H --> B
note["真实生成:每新增一个Token,都要重新执行一次前向计算
问题:长文本轮次多、延迟高、GPU并行潜力没有充分释放"]
投机解码的核心思路可以用一句话概括——“小模型猜、大模型验”。在每一步,先由一个轻量的草稿模型(draft model)基于当前上下文快速产出一批候选 Token(γ 个),再由目标大模型对这整批候选做一次并行前向校验:被接受的前缀直接采用,首个被拒绝的位置之后由大模型重新采样,从而把原本需要 γ 步的串行生成压缩成约 1 步的有效推进。
flowchart TD
A["输入上下文 x"] --> B["草稿模型:快速产出 γ 个候选 Token"]
B --> C["目标大模型:一次前向并行校验整批候选"]
C --> D{"逐位校验"}
D -->|"前缀接受"| E["采用有效前缀,推进生成"]
D -->|"某位拒绝"| F["该位起由大模型按自身分布重采样"]
F --> E
E --> G{"是否结束?"}
G -->|否| A
G -->|是| H["输出序列(分布 ≡ 大模型原生 AR)"]
投机解码最关键的工程价值是「无损」——它不会改变目标大模型的输出分布,最终生成结果与纯自回归(vanilla AR)逐字生成完全一致,只是更快。这意味着它可以无风险地叠加在任意已训练好的大模型之上,不需要微调大模型本身。
无损并非“猜对了就行”,而是有严格的数学保证,其根基是大模型自带的验证(校验)机制——通常采用拒绝采样(Rejection Sampling)/ 重要性采样(Importance Sampling):
换句话说:草稿只负责“提速猜”,大模型始终掌握“最终拍板权”,输出分布天然不被扭曲。
校验之所以快,是因为大模型可以一次性并行验证整批候选,而不是逐位串行等待。这依赖于 Transformer 对固定长度序列的整体并行运算能力(每个位置的 FFN / 注意力独立并行计算)。
还有一个常被忽略、却至关重要的保障:大模型的并行校验并不是“只判对错”——它在对这一整批候选做前向计算时,会直接重新算出一个目标分布下的预测 Token。这意味着:
一句话总结其性能边界:下限 = 原生 AR,上限 = 原生 AR ×(1 + 平均接受长度)。因此引入草稿模型只会提速、不会拖慢,这也是它敢在生产环境大规模部署的底气。
尽管 EAGLE / DFlash / DSpark 三代在“草稿怎么生成”上各不相同(详见第四章 分代技术详细解析),但它们的训练范式与推理范式是统一的:都是“让小模型学大模型的分布与特征,再交给大模型并行校验”。整个过程可拆成「训练样本生成 → 草稿模型训练 → 协同推理加速」三步。
训练分两段,第一段由大模型生成训练样本,第二段用这些样本训练草稿模型:
flowchart TD
A["训练语料(文本序列)"] --> B["目标大模型:一次前向"]
B --> C["训练样本:每位置 logits(概率分布)"]
B --> D["训练样本:每位置 隐藏特征 hidden states"]
C --> E["(logits + 隐藏特征 作为草稿模型的监督标签)"]
D --> E
flowchart TD
A["训练样本:logits + 隐藏特征"] --> B["轻量草稿模型训练目标:\n拟合大模型分布与特征"]
B --> C["训练完成的草稿模型\n(与大模型同源,接受率高)"]
推理阶段由草稿模型与大模型协同循环完成,大模型始终掌握最终拍板权:
flowchart TD
A["当前上下文"] --> B["草稿模型产出 γ 候选"]
B --> C["大模型一次前向并行校验(自带保底预测)"]
C --> D["接受最长有效前缀;\n拒绝位由大模型重采样"]
D --> E["更新上下文"]
E --> F{"结束?"}
F -->|否| A
F -->|是| G["完成生成"]
🎯 先把时间线讲清楚:投机解码最早(2023 年 Chen 等人的经典投机采样)的思路是拿一个同架构的独立小模型当草稿模型——即额外训练/部署一个同家族的小参数模型,用它先生成候选序列,再由大模型校验。但这套方案在实际部署里有几个致命弱点:① 要多训一个完整小模型,训练与部署成本高;② 小模型只能看到离散 token,与主模型分布偏差大,草稿接受率不高;③ 多一套模型=多一份显存与工程负担,加速比被小模型自身的推理开销吃掉不少。于是后续工作不再另起炉灶训小模型,而是直接复用大模型自己算好的中间层特征来生成草稿——把「草稿模型」从「额外的一个模型」变成了「主模型身上长出的一颗小脑袋」,既省训练又省部署,草稿与主模型同源、接受率也更高。下面 5.1~5.3 三代方案都遵循这一路线:不再依赖独立草稿模型。
flowchart TD
subgraph MAIN["主模型骨干(目标大模型)"]
direction TB
E["Embedding"] --> L1["Transformer 层 1"]
L1 --> L2["层 2 …"]
L2 --> LN1["层 N-1(次顶层)
输出隐层特征 h"]
LN1 --> LN["层 N(顶层 / LM Head)
h → logits(当前位分布)"]
LN --> TOK["采样 / argmax → 输出 Token"]
end
subgraph HEAD["草稿头(轻量草稿模型 · 自回归循环)"]
direction TB
HIN["输入:隐层特征 h
(主模型次顶层 / 上一步预测 h)"]
FC["轻量 FC + 小型自注意力"]
HPR["隐层特征 h(草稿头内部,在 logits 前)"]
LOGITS["预测:下一个位置的 logits"]
HIN --> FC
FC --> HPR
HPR --> LOGITS
HPR -.->|"反馈为下一步输入"| HIN
end
Input["输入上下文 C"] --> E
LN1 -->|"复用次顶层隐层特征 h"| HIN
LOGITS --> CAND["草稿候选 d1…dK(交由主模型并行校验)"]
classDef mainFill fill:#e1effe,stroke:#2563eb,stroke-width:1px;
classDef headFill fill:#e6f7e6,stroke:#16a34a,stroke-width:1px;
class MAIN mainFill;
class HEAD headFill;
flowchart TD
H["隐层特征 h"]
D1["p(d₁|C) 采样 d₁"]
D2["p(d₂|C, d₁) 采样 d₂"]
D3["p(d₃|C, d₁, d₂) 采样 d₃"]
DK["p(dK|C, d₁…dK₋₁) 采样 dK"]
H --> D1
D1 -->|"将 d₁ 嵌入送回草稿头"| D2
D2 -->|"将 d₁,d₂ 嵌入送回"| D3
D3 -->|"… 严格因果"| DK
DK --> OUT["K 个草稿候选
(文本连贯、逻辑不跳)"]
classDef sampleFill fill:#fdecea,stroke:#dc2626,stroke-width:1px;
class D1,D2,D3,DK sampleFill;
flowchart TD
DRAFT["草稿候选 d1…dK"]
MAINV["主模型一次前向
并行计算全部 K 位 logits"]
COMP["逐位比较
p_target 与 p_draft 分布"]
COMP -->|"p_target ≥ p_draft"| ACC["必然接受"]
COMP -->|"p_target < p_draft"| RAND["以概率 p_target/p_draft
随机接受"]
ACC --> OUT["接受前缀 + 纠正错误位
进入下一轮"]
RAND --> OUT
classDef vFill fill:#e6f7e6,stroke:#16a34a,stroke-width:1px;
classDef acceptFill fill:#e1effe,stroke:#2563eb,stroke-width:1px;
class MAINV vFill;
class ACC,RAND acceptFill;
技术逻辑与底层机制:
EAGLE 的核心创新在于“无独立草稿模型”的设计范式。它不额外加载另一个小语言模型,而是在主模型的 Transformer 层顶部嫁接一个轻量级“草稿头”(Draft Head),该草稿头通常由 1~2 层全连接网络组成,参数量仅为主模型的 1% ~ 3%。其工作流程分为三步:
优势深度剖析:
固有短板与工程代价:
flowchart TD
subgraph MAIN["目标模型骨干(frozen,仅前向取特征)"]
direction TB
E["Embedding"] --> L2["层 2"]
L2 --> LMID["… 中间若干层 …"]
LMID --> LN2["层 N-2(倒数第二层)"]
LN2 --> LN["层 N(顶层 / LM Head)
→ logits / Token(主干自身输出)"]
end
subgraph FUSE["跨层融合 + KV 注入"]
direction TB
H["抽取并融合多层隐层特征 h"]
KV["F 拆为 K / V 注入草稿模型"]
H --> KV
end
subgraph PREDICT["并行草稿预测器(轻量 Transformer · K 个输出头)"]
direction TB
H1["输出头 1 → logits 1"]
H2["输出头 2 → logits 2"]
HK["输出头 K → logits K"]
end
L2 -->|"隐层特征 h"| H
LMID -->|"隐层特征 h"| H
LN2 -->|"隐层特征 h"| H
KV --> H1
KV --> H2
KV --> HK
classDef tFill fill:#e1effe,stroke:#2563eb,stroke-width:1px;
classDef fFill fill:#fef9e7,stroke:#d97706,stroke-width:1px;
classDef headFill fill:#e6f7e6,stroke:#16a34a,stroke-width:1px;
class MAIN tFill;
class FUSE fFill;
class PREDICT headFill;
flowchart LR
A["anchor 锚点 Token"]
M["同批 K 个位置
一次性输入"]
PP["并行预测器
单次前向(矩阵运算)"]
D1["候选 d1"]
D2["候选 d2"]
DK["候选 dK"]
A --> PP
M --> PP
PP --> D1
PP --> D2
PP --> DK
D1 --> CAND["批量候选 [d1…dK]
一次生成 · 无 Loop · 无因果依赖"]
D2 --> CAND
DK --> CAND
classDef genFill fill:#e6f7e6,stroke:#16a34a,stroke-width:1px;
class PP genFill;
class CAND genFill;
flowchart TD
CAND["批量候选 [d1…dK]"]
V["主模型一次前向并行校验 K 位"]
CMP["贪心对比 argmax
(从左到右逐位比对)"]
CMP -->|"一致"| KEEP["保留该位继续"]
CMP -->|"不一致"| CUT["立即截断"]
KEEP --> CMP
CUT --> OUT["接受前缀 + 纠正
进入下一轮"]
OUT --> TF["⚠️ 常见现象:
位置越靠后接受率越低
(位置独立假设在自然语言中不成立)"]
classDef vFill fill:#e6f7e6,stroke:#16a34a,stroke-width:1px;
classDef warnFill fill:#fdecea,stroke:#dc2626,stroke-width:1px;
class V,CMP vFill;
class TF warnFill;
技术逻辑与底层机制:
DFlash 彻底颠覆了草稿生成的因果范式,采用 非自回归(Non-Autoregressive, NAR) 思想。它抛弃了“必须等前一个 Token 才能预测下一个”的约束,使用一个多输出头并行预测器(Multi-Head Parallel Predictor),一次性同时预测未来 K 个位置的 Token 概率分布。其核心设计包含:
优势深度剖析:
| 并行头 | 候选1(概率) | 候选2(概率) |
|---|---|---|
| 头1 | 好 — 0.8 | O — 0.7 |
| 头2 | K — 0.8 | 吧 — 0.7 |
固有短板与数学困境:
flowchart TD
subgraph TM["🎯 目标模型(一次前向产出锚点 token D)"]
direction LR
P["Prompt A B C"] --> F1["目标模型前向"] --> D["锚点 D"]
end
D --> PB
subgraph PB["⚡ 并行主干 Parallel Backbone(单前向 · 多头并行产出 γ 个 base logit)"]
direction LR
IN["输入:锚点 D"] --> FWD["一次前向计算(复用目标特征 / KV 注入)"]
FWD --> U1["U₁"]
FWD --> U2["U₂"]
FWD --> U3["U₃"]
FWD --> U4["U₄"]
end
subgraph SEQ["🔗 轻量串行序列头 Sequential Block(Markov 头 · 逐位串行链接)"]
direction LR
X0["x₀ = D(锚点)"]
X0 -->|"B(x₀,·) 低秩转移偏置
W₁[x₀] · W₂"| X1["x₁"]
X1 -->|"B(x₁,·)"| X2["x₂"]
X2 -->|"B(x₂,·)"| X3["x₃"]
X3 -->|"B(x₃,·)"| X4["x₄"]
end
U1 -->|"+B 校正"| X1
U2 -->|"+B 校正"| X2
U3 -->|"+B 校正"| X3
U4 -->|"+B 校正"| X4
X1 --> C1["c₁ 置信度"]
X2 --> C2["c₂"]
X3 --> C3["c₃"]
X4 --> C4["c₄"]
C1 --> SCH
C2 --> SCH
C3 --> SCH
C4 --> SCH
SCH["🧮 硬件感知前缀调度器
累计存活概率 ∏cᵢ 全局贪心选取"] --> KEEP["✅ 保留高置信前缀 E F G"]
SCH --> DROP["🗑 丢弃低置信 H"]
KEEP --> VER["目标模型并行校验(一次前向)"]
DROP --> VER
VER --> OUT["接受 E,F · 拒绝 G · 纠正生成 G*"]
classDef tFill fill:#e1effe,stroke:#2563eb,stroke-width:1px;
classDef pFill fill:#fff3e0,stroke:#f59e0b,stroke-width:1px;
classDef sFill fill:#e6f7e6,stroke:#16a34a,stroke-width:1px;
classDef cFill fill:#fef9e7,stroke:#d97706,stroke-width:1px;
classDef vFill fill:#ede9fe,stroke:#7c3aed,stroke-width:1px;
class TM tFill;
class PB pFill;
class SEQ sFill;
class C1,C2,C3,C4 cFill;
class SCH,KEEP,DROP,VER,OUT vFill;
flowchart TD
DRAFT["草稿候选 d1…dγ"]
CH["置信度头
预测每位置条件接受概率 c_k
(sigmoid + STS 校准)"]
SCH["硬件感知调度器
按累计存活概率 ∏c_i 从高到低贪心选取
结合吞吐曲线 SPS(B) 最大化全局吞吐"]
VER["只对裁剪后的前缀
做一次增量校验"]
DRAFT --> CH --> SCH
SCH -->|"动态验证长度 ℓ"| VER
VER --> OUT["接受前缀 + 拒绝重采样"]
classDef cFill fill:#fef9e7,stroke:#d97706,stroke-width:1px;
classDef vFill fill:#e6f7e6,stroke:#16a34a,stroke-width:1px;
class CH,SCH cFill;
class VER vFill;
flowchart LR
DS["DSpark
DeepSeek-V4 在线系统"]
G1["⚡ 单用户生成速度提升
V4-Flash +60%~85%
V4-Pro +57%~78%"]
G2["📈 严格交互 SLA 下
保持稳健吞吐,突破性能悬崖"]
G3["🎯 移位服务系统
吞吐–交互性帕累托前沿"]
DS --> G1
DS --> G2
DS --> G3
classDef gainFill fill:#e6f7e6,stroke:#16a34a,stroke-width:1px;
class G1,G2,G3 gainFill;
下面先用 3 张图分别把 DSpark 的「架构(图13)、调度机制(图14)、生产收益(图15)」拆开讲解,再补充技术公式与实测数据:
技术逻辑与底层机制:
DSpark 提出了 半自回归(Semi-Autoregressive) 混合架构:以高速的全并行主干打底,再叠加一个轻量串行序列头恢复块内 Token 依赖,旨在调和 EAGLE 与 DFlash 的矛盾。它的设计包含三个核心协同组件:
| 阶段一(并行粗猜) | 候选1(概率) | 候选2(概率) |
|---|---|---|
| 头1 | 好 — 0.8 | O — 0.7 |
| 头2 | K — 0.8 | 吧 — 0.7 |
| 阶段二(串行校正后) | 候选1(概率) | 候选2(概率) |
|---|---|---|
| 头1 | 好 — 0.8 | O — 0.7 |
| 头2 | 吧 — 0.8 | K — 0.7 |
优势深度剖析(含论文实测数据):
固有短板与系统代价:
纯客观维度对比,无主观渲染、无营销修饰。 三代技术代表了投机解码领域从“因果串行”到“全并行”再到“混合自适应”的演进路径。其中 DSpark 数据已根据 arXiv:2607.05147 生产环境实测结果更新。
| 技术方案 | 生成范式 | 硬件资源消耗 | 并发支持能力 | 架构核心特征 |
|---|---|---|---|---|
| EAGLE | 串行因果生成 | 较高(依赖主模型高层特征,显存占用大) | 弱(串行逻辑限制,仅适配低并发) | 依托主模型隐层特征,草稿因果合规,稳定性强 |
| DFlash | 无约束全并行生成 | 较低(轻量级骨干,显存友好) | 极强(天然适配高负载集群,压满GPU算力) | 批量并行生成Token,硬件利用率拉满,单轮生成量大 |
| DSpark | 半回归并行 + 串行校正 | 中等(骨干+校正头,架构最重但调度灵活) | 强(带硬件动态感知调度器) | 并行生成打底(提速度)+ 串行校正纠错(提质量),动态适配GPU负载 |
| 技术方案 | 实测端到端加速比(vs Vanilla AR) | Token 接受率 | 核心优势指标 |
|---|---|---|---|
| EAGLE | 2.0x ~ 3.0x | 最高(~70%+) | 单步猜测极准,无效校验最少,出字丝滑 |
| DFlash | 3.0x ~ 4.0x(理论上限最高) | 较低(~30%~45%) | 纯计算吞吐量最大,能把GPU算力吃到极致 |
| DSpark | 2.9x ~ 3.7x | 较高且平稳(不随位置衰减) | 位置级条件接受率全程高位稳定,打破了并行生成“越往后越不准”的物理定律 |
| 技术方案 | 核心缺陷(痛点) | 最适合的业务场景 | 工程落地难度 |
|---|---|---|---|
| EAGLE | 串行计算,无法利用GPU并行算力,高并发下吞吐量是瓶颈 | 单路低延迟(如实时语音助手、交互式编程) | 中等(逻辑清晰,但显存优化较难) |
| DFlash | 无因果依赖,逻辑断裂严重,无效校验多(有效通过率低) | 高并发离线批量(如海量文档翻译、数据清洗) | 最低(代码轻量,调大Batch Size即可) |
| DSpark | 架构复杂,调度逻辑重,工程部署与调优成本极高 | 混合负载生产环境(既要并发又要低延迟,且有顶级工程团队) | 最高(调度器需深度定制,Debug周期长) |
相关论文链接:
📄 EAGLE: Speculative Sampling Without a Draft Model (arXiv:2311.16867) 📄 DFlash: Draft‑free Speculative Decoding via Parallel Token Generation (arXiv:2408.13074) 📄 DSpark: Confidence-Scheduled Speculative Decoding with Semi-Autoregressive Generation (arXiv:2607.05147)✅ 一句话总结: 投机解码用“小模型猜、大模型验”的范式,将大模型推理从“串行等”变为“并行验”,在保证精度无损的前提下,实现 2~4 倍的推理加速,是大模型高效部署的关键技术之一。
本文档基于公开论文与行业技术报告整理,内容持续更新。欢迎反馈与指正。