Qwen3.5 树形投机解码:混合架构下的验证策略
模型: Qwen3.5-9B
前置阅读: Speculative Decoding · EAGLE 系列 · MTP · Qwen3.5 架构
一句话总结: Qwen3.5 的 3+1 混合架构让树形投机解码必须同时处理两种验证机制——Full Attention 层用 tree attention mask 并行验证,Gated DeltaNet 层用 fork/checkpoint 逐深度处理。性能开销 <2%,内存是真正的代价。
一、为什么要做树形验证
经典投机解码的链式 draft-verify 一次只验证一条路径:
1 | 链式草稿: I → make → a → plan |
如果第 2 个 token “make” 被拒绝,后面的 “a”、”plan” 即使猜对了也没用——因为它们的前提已经不成立了。
树形验证的思路是:在每个位置保留 top-k 个候选,形成一棵 draft tree,一次 forward 验证所有路径。
1 | 树状草稿: I |
EAGLE-2 用置信度驱动的动态草稿树,把平均接受长度从 3.7 提升到 4–5.5。树形验证的收益很直接:同样一次 target model forward,链式最多验证 γ 个 token,树形可以覆盖 k^d 条路径。
对于纯 Transformer 模型,树形验证几乎是”免费的”——通过 tree attention mask,一次 forward pass 就能并行验证整棵树。但 Qwen3.5 的混合架构打破了这个前提:3/4 的层是 Gated DeltaNet(线性注意力),它们不支持 attention mask。
二、Tree Attention Mask 回顾
先回顾纯 Transformer 下的树形验证是怎么做的(详见 EAGLE 文章的 Tree Attention 部分)。
草稿树被展平为一维序列送入 target model,但不同分支之间不应该互相看到。Tree attention mask 通过定制每个 token 的可见范围来解决这个问题:每个 token 只 attend 自己从根到该节点路径上的祖先。
1 | It |
展平序列:[It, is, has, a, the, to]
tree attention mask:
1 | It is has a the to |
“a” 只能看到 [It, is, a]——从根到它的完整路径。”has”、”the”、”to” 对 “a” 完全不可见。同一次 forward pass 中,target model 对每条路径独立计算了概率分布,等价于逐条路径单独验证,但只付出一次 forward 的代价。
对于纯 Full Attention 的 Transformer,这套方案完美且零额外成本。问题出在 Qwen3.5 的 32 层里有 24 层不是 Full Attention。
三、混合架构的挑战
Qwen3.5 的 3+1 混合设计:每 4 层为一组,前 3 层 Gated DeltaNet(线性注意力),第 4 层 Full Attention。
1 | Block 0: [GDN] [GDN] [GDN] [FullAttn] Layer 0- 3 |
当一棵草稿树送入 target model 时,不同类型的层需要不同的验证策略:
Full Attention 层(8 层)
完全支持 tree attention mask。和纯 Transformer 一样,展平序列 + 定制 mask,一次 forward 并行验证所有路径。没有额外开销。
Gated DeltaNet 层(24 层)
问题的核心在于 GDN 的状态更新方式。回顾 GDN 的状态更新公式:
问题 1:不能用 mask 隔离分支。
Full Attention 中,attention mask 控制每个 query 能看到哪些 key/value。但 GDN 的”记忆”不在 KV cache 里,而在状态矩阵
1 | Full Attention:每个 token 有独立的 KV 条目 → mask 控制可见范围 → 分支隔离 |
问题 2:状态更新不可逆。
如果按展平顺序 [It, is, has, a, the, to] 处理,处理完 “is” 后
1 | 展平序列处理: |
更糟糕的是,
四、解决方案:Fork/Checkpoint
解法很直接:在分支点保存
以一棵简单的 k=2, depth=2 的树为例:
1 | root |
GDN 层的处理流程:
1 | 1. 从当前 S₀ 出发 |
每个叶子节点最终拥有独立的
逐深度处理
实际实现中,更高效的做法是按深度分层处理(depth-by-depth):
1 | 深度 0:处理 [A, B] |
同一深度的所有节点可以并行处理——它们互相之间没有依赖,只依赖各自父节点的 checkpoint。
分层协同
关键是:GDN 层和 Full Attention 层在同一轮验证中用不同策略,但处理的是同一棵草稿树。
1 | Layer 0 (GDN): depth-by-depth + fork checkpoint |
GDN 层处理完后,hidden states 被传给 Full Attention 层,后者照常用 tree mask 做并行验证。两种机制在层与层之间无缝衔接。
五、Checkpoint 的双重用途
Checkpoint 机制不仅用于树形分支,还用于验证后的回滚。
用途 1:树形分支(验证阶段)
上文已详述。在分支点 fork 状态矩阵,每条路径独立演化。
用途 2:拒绝后回滚
验证完成后,target model 接受了最长的合法路径(比如 root → A → C),拒绝了其他分支。此时需要把 GDN 的状态回滚到被接受的最后一个 token 对应的
1 | 验证结果:接受 root → A → C,在 C 之后拒绝 |
这个回滚对于链式验证同样必需——如果链式草稿 [t₁, t₂, t₃, t₄, t₅] 中
1 | 链式验证也需要 checkpoint,这不是树形独有的问题。 |
六、开销分析
内存开销
单个 checkpoint 需要保存 24 层 GDN 的全部状态矩阵:
1 | 单个 checkpoint = 24 层 × 16 key_heads × 128(K_dim) × 128(V_dim) × 2 bytes |
不同验证策略的 checkpoint 总内存:
| 策略 | checkpoint 数量 | 总内存 |
|---|---|---|
| 链式(γ=5) | 5 | 60 MB |
| 树形(k=2, d=3, ~15 节点) | 15 | 180 MB |
| 树形(k=3, d=3, ~40 节点) | 40 | 480 MB |
性能开销
Fork 操作的本质是 memcpy 一个 12 MB 的状态矩阵:
1 | fork 一次 ≈ memcpy 12 MB |
整棵树所有分支点的 fork 总计几十次,总耗时约几 ms。相比 target model 一次 forward pass(通常几十到上百 ms),fork 的性能开销 <2%。
1 | 性能:几乎无损失(<2%) |
七、完整验证流程
以 Qwen3.5-9B 为例,一轮完整的 draft-verify 流程:
Step 1:MTP Module 生成树形草稿
Qwen3.5 内置的 MTP module 是串行设计(mtp\_num\_hidden\_layers: 1),可以自回归循环生成任意深度的草稿。配合 top-k 采样,每步产生 k 个分支,自然形成树状结构。
1 | MTP Module → 预测 t+1 → top-k 采样 → k 个候选 |
这和 EAGLE 的 Autoregression Head 本质相同——区别在于 MTP module 是预训练时联合训练的,EAGLE 是事后训练的。
需要注意:Draft 阶段只跑 MTP module(1 层 decoder),不经过主模型的 32 层。MTP module 用上一步主模型 forward 的 hidden state 作为起点,之后在自己内部自回归循环。主模型的 GDN 状态管理问题只出现在下面的 verify 阶段。
Step 2:展平草稿树
将树上所有节点展平为一维序列,同时构造:
- Tree attention mask(供 Full Attention 层使用)
- 树的拓扑信息:每个节点的父节点索引(供 GDN 层确定 fork 关系)
Step 3:送入 Target Model 的 32 层
1 | 对每个 Block(共 8 个): |
Step 4:验证与回滚
LM Head 把最终 hidden states 映射为 token 分布,逐路径验证。找到最长被接受的路径后:
1 | Full Attention 层: |
下一轮 draft-verify 从恢复后的状态继续。
八、优化策略
控制树的规模
最直接的优化——限制树的宽度 k 和深度 d,控制 checkpoint 总数:
1 | k=2, d=3 → 约 15 个节点 → 180 MB checkpoint |
树的规模应根据可用内存动态调整。
选择性 Fork
结合 EAGLE-2 的置信度机制:如果某个分支的 draft 置信度很高(>0.95),可以跳过 fork——因为这个分支几乎确定会被接受,不需要为它保留回滚点。
1 | 置信度 > 0.95 → 直接处理,不保存 checkpoint |
高置信度节点占比通常不低,选择性 fork 可以显著减少 checkpoint 数量。
Checkpoint 压缩
子节点的
delta 通常是稀疏的(只有被当前
九、总结
Qwen3.5 的混合架构让树形投机解码必须同时协调两种验证机制:
1 | Full Attention 层(8 层): |
关键结论:
- Fork/checkpoint 同时解决两个问题:树形分支(验证时)和拒绝后回滚(验证后)
- 链式验证同样需要 checkpoint(用于回滚),树形只是需要更多
- 性能几乎无损失,内存是唯一需要权衡的维度
- MTP module 天然支持树形草稿——串行设计 + top-k 采样即可构造 draft tree
混合架构下的树形投机解码不是一个新问题的出现,而是同一个 fork/checkpoint 机制的两种应用场景的统一。理解了这一点,Qwen3.5 上的树形投机与纯 Transformer 上的树形投机在工程实现上的差异就只剩一个:GDN 层需要额外维护一个 checkpoint 栈。