SPEC-RL: Accelerating On-Policy RL with Speculative Rollouts

Xiamen U. × Shopee × Tsinghua · Bingshuai Liu, Ante Wang, Zijun Min et al. · arXiv:2509.23232 (v3, 2026-01-12)
关键词: RLVR · speculative decoding · rollout reuse · GRPO/PPO/DAPO · lenience

速读卡片 (TL;DR)

一句话:上一个 epoch 的 rollout 当 draft,在当前 policy 下做 speculative verify,接受的前缀直接复用、第一个被拒位置之后再用当前 policy 续写——不用新增 draft model,纯 rollout-stage 的"插件式"加速,2–3× 而不掉点。

2.31×
9 个 model×algo 组合的平均加速
−66%
decoded tokens 减少
50–70%
连续两 epoch ROUGE-1 token overlap

立场:这条路线里最"轻"的一篇——核心创新只是"draft = 上一轮自己"。简单到几乎不像 paper,但正因如此它揭示的是 RLVR 训练里一种被普遍浪费掉的结构性冗余。


1 · 动机:为什么"上一轮的轨迹"是免费的 draft

1.1 历史脉络

RLVR (Reinforcement Learning with Verifiable Rewards) 已经成为推理模型训练的主流——DeepSeek-R1、Tülu-3、Qwen3 都靠它。但把一个 RL step 拆开看,rollout 占了大头:在 8B 模型上 generation 通常吃掉 60–70% 的 step time(NeMo-RL 论文给的是 65–72%)。当模型从 1.7B 涨到 32B、单条 trajectory 从 512 token 涨到 4k 甚至 32k(long-CoT、agentic 多轮)时,这个比例只升不降。

已有的加速思路大致三条:

  1. 并行 rollout(Xu et al. 2025)——更多 GPU 同时跑,边际收益递减、同步开销升高。
  2. 修改目标 / 数据(CPPO、Prefix Grouper、各种 down-sampling)——往往引入 bias 或者打破 on-policy 假设。
  3. replay buffer——直接复用旧轨迹做训练数据,但 policy 一变就 stale。

SPEC-RL 选了第四条,和 NeMo-RL 那篇用 EAGLE-3 的思路同源 (speculative decoding),但把 draft model 替换成了"上一个 epoch 的 cache"。换句话说,draft 是免费的——你训练的时候本来就在生成它。

1.2 别的方案为什么不够

方案核心思路主要妥协
Parallel rollout更多机器并发跑 rolloutGPU 翻倍才能换 1.x×;同步成本增长
CPPO / 数据精选只 update 信息量大的 sample引入 selection bias,与 on-policy 冲突
Replay buffer把旧 trajectory 直接当训练数据policy 一变就严重 off-policy
EAGLE-3 + RL (NeMo-RL)训练一个独立 draft head 配 target多一个 model 要 maintain;draft 还得跟着 policy 重训
RhymeRL从 history 建 suffix tree,做 token 级 SD系统复杂、suffix-tree 维护成本
SPEC-RL (本文)上一 epoch 的 rollout 作为 draft + lenience需要小数据集多 epoch;首 epoch cold start

1.3 为什么这事不平凡

"复用旧轨迹"听上去显然——但要做对,有几个非平凡的点:

Figure 2 复刻: epoch 间 ROUGE-1 token overlap 0.5 0.6 0.7 epoch 2 epoch 16 GRPO PPO DAPO
训练过程中相邻 epoch 的 token overlap (用 ROUGE-1 量) 长期稳定在 0.5–0.7 区间。这就是"上一轮 rollout 当 draft"在统计上能 work 的根因——一半到三分之二的 token 本来就会被重新生成成几乎一样。

2 · 背景速查

术语含义
RLVRRL with Verifiable Rewards——reward 是 0/1 的可验证信号 (数值匹配 / unit test 通过)
rollout一次完整生成 y ∼ π(·|x),RL 训练数据来源
on-policy训练数据必须用当前 πθ 采样;PPO/GRPO 的核心假设
draft & verifySD 范式:draft p 提议、target q 并行验证、按比率接受
acceptance probαi = min(1, q/p) 保证最终从 q 采样
lenience ℓ放宽接受准则的乘子,ℓ=1 复原标准 SD,ℓ→∞ 全部复用
epochRLVR 里一个 epoch = 全部 prompt 都被 rollout 一遍
verified prefix从位置 1 起连续被接受的 token,直到第一个 rejection 位置 n
Standard speculative decoding 复习: draft p 给出 z1..k,target q 算 q(zi|·) 并以 αi=min(1, q/p) 接受。在第一个 rejection 处用 (q − p)+ 重采样一个 token,然后停。整个采样链等价于从 q 直接采,这是 Leviathan et al. 2023 的核心数学结论。SPEC-RL 把 (p, q) 替换为 (πprev, πcurr),把 z 替换为 yprev,一切机制平移过去。

3 · 核心机制:Speculative Rollout

3.1 整体流程

每个 prompt x 在 epoch t 的 rollout 流程:

  1. 从 cache 取出 epoch t−1 时同一 prompt 生成的 yprev,以及当时的 token 概率 pprevi = πprev(yprevi | x, yprev)。
  2. 在当前 πθ 上做一次并行 forward 整条 yprev,得到 pcurri。这是单次 prefill,不是逐 token 解码——这就是 SD 加速的来源。
  3. 对每个位置 i 计算 α̃i = min(1, ℓ · pcurri/pprevi),抽 u ∼ U(0,1),u > α̃ ⇒ reject。
  4. 取第一个 rejection 位置 n,verified prefix = yprev
  5. 从位置 n 起,用 πθ 自回归续写得到 ycurr≥n
  6. 最终 ycurr = yprev ⊕ ycurr≥n,写回 cache 覆盖旧值。
Prompt x Epoch t−1 cache: "Let" "x" "=" "3" "," "so" "y²" "=9" πθ 并行 verify (一次 prefill): accept accept accept accept accept REJECT discard discard πθ 从位置 n=6 起续写: "thus" "y²" "=9" "…" draft verify generate
核心机制示意:cache 里的旧 rollout 喂给当前 πθ 做一次并行 forward,逐 token 计算 ratio 决定接受/拒绝。在第一个 rejection (位置 6) 之前的 verified prefix 直接复用,从位置 6 起切换为正常自回归生成。整条最终序列在分布上等价于"从 πθ 全新采样" (ℓ=1 时严格成立)。

3.2 Worked example: 一道数学题在 epoch 5 → 6 的演化

Prompt: x = "Solve x²=9, find y if y=x+0."。Epoch 5 cache 里的 yprev 是 8 个 token: ["Let","x","=","3",",","so","y²","=9"],每个位置上 πprev 的概率分别是 [0.45, 0.78, 0.91, 0.62, 0.55, 0.48, 0.30, 0.40]

Epoch 6 时 πθ 微调过,在同样上下文下给出概率 pcurr = [0.50, 0.80, 0.92, 0.65, 0.58, 0.20, 0.31, 0.42]。注意位置 6 的 "so" 概率从 0.48 掉到 0.20——πθ 现在更倾向于直接说 "thus"。取 ℓ = e0.5 ≈ 1.649,逐位算 α̃:

itokenpprevpcurrratioα̃ = min(1, ℓ·ratio)u结果
1"Let"0.450.501.1111.0000.31accept
2"x"0.780.801.0261.0000.62accept
3"="0.910.921.0111.0000.04accept
4"3"0.620.651.0481.0000.71accept
5","0.550.581.0551.0000.22accept
6"so"0.480.200.4170.6870.84REJECT (n=6)

verified prefix = 5 个 token。从位置 6 起 πθ 接管自回归生成,可能给出 ["thus","y²","=9","…"]。最终拼起来的 ycurr:5 个旧 token + ~k 个新 token。如果 prev 长度是 800、reused 600、新生成 200,那就只解码了 200 个 token,加上 1 次 prefill 跑 800 token——prefill 在 GPU 上比逐 token decode 高效 1–2 个数量级,这就是加速的物理来源。

3.3 反向论证: 如果省掉 verify 直接拼接会怎样?

就成了 "Random Reuse" 消融——论文 Table 2 给出的对照: token 反而更多 (304.5M vs 182.7M),但 average accuracy 从 37.3 掉到 31.4。原因是无验证地拼接相当于把上一轮 πprev 的 sampling 噪声直接注入当前的训练数据,policy gradient 用错了 logπ,KL 爆炸,训练偏移。这条消融非常重要——它证明 "speculative verify 这一步" 不是装饰,是把"复用"和"on-policy"调和起来的关键。


4 · Lenience 参数 ℓ 的物理意义

ℓ 是 SPEC-RL 唯一新加的超参,直接控制"宁可激进复用还是宁可保 on-policy":

α̃i = min(1, ℓ · πcurr(yi|...) / πprev(yi|...))
语义含义论文实测 speedup / acc
→ 0所有 token 都拒绝退化为 vanilla RLVR1.00× / 34.9
= 1标准 SD,无损分布严格 = πcurr1.22× / 35.8
= e0.2轻微宽松少量 off-policy1.86× / 36.3
= e0.5论文推荐 sweet spot速度/质量最佳平衡2.29× / 37.3
= e0.8偏激进开始掉精度2.64× / 33.9
= e2.0很激进明显劣化3.05× / 30.3
→ ∞全盘复用完全 off-policy14.86× / 29.2 (训练崩)
ℓ 与 (speedup, accuracy) 的取舍曲线 29 33 37 acc speedup ℓ=1 e^0.2 e^0.4 e^0.5 e^0.8 e^2 sweet spot
ℓ 的非单调权衡: 准确率(实线/橘)和加速(虚线/蓝)在 ℓ ≈ e0.5 处达到最佳平衡。再激进的话 KL 爆炸、entropy 失控,训练就跑偏了 (Figure 5 的 clip ratio、KL 对应区间也开始飙升)。

诊断指标 (Figure 5): 当 ℓ < e0.5 时,clip fraction 稳定 < 0.0025、KL < 0.1、entropy 与 baseline 几乎重合;一旦 ℓ ≥ e1.0 这三个量同时炸,训练失稳。这给了一个非常实用的经验:把 KL 当 ℓ 的早期警报

反向论证: 为什么不能直接把 ℓ 设成 ∞?因为这等价于强制把 πprev 的整条 trajectory 当作 πcurr 的样本——用错了 log-prob,policy gradient 的方向直接错了。Table 3 里 ℓ→∞ 的 14.86× 速度看着很美,但 acc 29.2 比不训还差。这是"speedup ≠ benefit"的典型反例。


5 · 系统实现

5.1 Cache 模块

每个 prompt 维护一个最新 rollout(包括 token 序列和当时的 token-level log-prob)。"最新"意味着每个 epoch 把生成的 ycurr 写回去,覆盖前一个 yprev。这一点很关键——消融里 "Delayed Reuse"(用 epoch t−2 而非 t−1 的轨迹)直接把 speedup 从 2.29× 降到 1.44×,因为 policy gap 越大,reuse rate 越低。

5.2 批量 verify

实现层面,作者把整个 batch 的 prompt + 对应 cached prefix 拼成一个 padded batch,左 pad 对齐,送进 vLLM 一次 forward 拿到 logits,所有 prompt 并行 verify。这避免了"每条 prompt 单独验证"导致的 GPU 利用率塌陷。完成 verify 后,只对那些"还要继续生成"的 prompt 再发起 vLLM continuation request。

系统层面: 一个 RL step 内 SPEC-RL 在 vLLM 上的两阶段调用 Batch (1024 prompts) prompt + yprev left-padded 从 cache Stage 1: Verify vLLM single prefill 全 batch 一次 forward 拿到 logits → α̃ → n Stage 2: Continuation vLLM continue from yprev<n 仅生成 ~200 tok/seq (vs baseline 800) 写回 cache (覆盖 epoch t−1 的内容)
系统视角: 一个 step 里 SPEC-RL 把原本 1 次自回归 generation 拆成 (1) 一次 batched prefill 做 verify + (2) 一次较短的 continuation。两次都是标准 vLLM 调用,不需要改 vLLM kernel。

5.3 Worked example: batch 维度的吞吐

设 batch=1024,平均 yprev 长度 = 800,平均 reused = 600,新生成 = 200。


6 · 公式推导与数值敏感性

原版 SD 的接受概率 (Leviathan et al. 2023):

αi = min(1, q(zi)/p(zi))

SPEC-RL 把 (p, q) 替换成 (πprev, πcurr) 并加入 lenience:

α̃i = min(1, ℓ · πcurr(yprevi|x, yprev<i) / πprev(yprevi|x, yprev<i))

物理直觉: ratio = πcurrprev 衡量"在新 policy 眼里这个 token 还有多自然"。当两个 policy 几乎一样时 ratio ≈ 1,token 几乎都被接受;当 policy 在某个位置剧烈分歧时 ratio ≪ 1,大概率拒绝。乘以 ℓ 相当于给 ratio 一个全局放大,鼓励"勉强还行的 token 也接受"。

数值敏感性 (固定 ratio = 0.5,看 ℓ 变化):

ℓ·ratioα̃解释
0.50.250.25更挑剔,接受 25%
1.00.500.50标准 SD,接受 50%
1.50.750.75明显宽松
2.01.001.00无条件接受
5.02.501.00同上,饱和了

关键观察:对 ratio = 0.5 这种"中等分歧"的 token,ℓ 从 1 涨到 2 就把接受率从 50% 拉到 100%——非线性放大。这也是为什么 ℓ = e0.5 ≈ 1.65 已经显著改善 reuse rate。

反向: 当 ratio > 1/ℓ 时永远 accept。 也就是只要新 policy 在该 token 的概率不比旧 policy 低太多,就直接接受。具体边界: ℓ = e0.5 ⇒ 只要 πcurr ≥ 0.607 · πprev 就 100% accept。


7 · 实验关键结果

7.1 主表 (Table 1) 摘录

ModelAlgoTokens (M) ↓SpeedupAVG accbaseline acc
Qwen3-1.7BGRPO554.8 → 182.72.29×37.334.9 (+2.4)
Qwen3-1.7BPPO565.1 → 230.81.94×35.034.8 (≈)
Qwen3-1.7BDAPO543.1 → 171.62.17×32.831.9 (+0.9)
Qwen3-8BGRPO1033 → 3362.51×59.357.5 (+1.8)
Qwen3-8BPPO984 → 4001.94×57.257.3 (≈)
Qwen3-8BDAPO1052 → 3262.88×57.355.0 (+2.3)
Llama3.2-1BGRPO554 → 1622.60×15.515.2 (+0.3)

读表: 9 个组合全部加速 1.94×–2.88×,平均 2.31×。准确率没掉,常常还有 +1~2 分提升 (尤其 OOD: Qwen3-8B GRPO 的 IFEval 从 41.2 → 47.7,+6.5)。这与"reuse old prefix → 训练数据多样性下降"的直觉相反——Figure 6 给出解释: 早期 epoch 的 prefix 比晚期更多样(那时 policy 还没收敛),复用早期 prefix 反而保住了 trajectory diversity。

7.2 关键消融 (Table 2)

变体TokensSpeedupAVG acc结论
SPEC-RL (ours)182.7M2.29×37.3baseline
Random Reuse304.5M2.35×31.4没 verify ⇒ 数据被污染
Delayed Reuse (t−2)308.8M1.44×36.3cache 越旧 reuse rate 越低

这两个消融在我看是论文最重要的——它们分别证伪了两种"看起来更简单"的选择: 不验证(直接拼接)、不及时更新 cache(用更旧的 trajectory)。两条都比 SPEC-RL 差。

7.3 训练动力学 (Figure 4-5)


8 · 与同类工作对比

方法Draft 来源Verify 严格性系统复杂度典型加速主要妥协
SPEC-RL上一 epoch 自己的 rolloutSD + lenience (ℓ可调)极低 (一个 cache)2–3×需多 epoch 训;cold start
NeMo-RL × EAGLE-3训一个 EAGLE-3 draft head严格 SD,无损高 (要重训 draft、要 vLLM 集成)1.4× (8B sync) ~ 2.5× (235B async)多一个 model 维护
ReSpec (Sun et al. 2025)独立 draft model + 适配 RLSD,有 fidelity 控制1.5–2×draft 仍要重训
DAS / RhymeRL历史回答构建 suffix tree,token 级匹配SD on tree branch高 (suffix tree 维护)1.5–2×tree 内存占用、匹配复杂
Replay buffer历史轨迹直接当训练数据不验证(节省 rollout 数,不是单条 rollout 加速)off-policy 偏差

纵观三篇:

四者并不严格冲突:SPEC-RL 的"上一 epoch 整条 cache" 可以看作 DAS 的特例 (匹配整条 history, 不分 token);反过来 SPEC-RL 也可以叠加 EAGLE-3 做"小段填充"。论文没做这种组合实验,但这是显然的后续。


9 · 局限 / 个人 take / 待验证问题

待验证问题清单 (按优先级)
  1. SPEC-RL × EAGLE-3 组合: verified prefix 之后的 continuation 阶段能否再叠 EAGLE-3 加速?
  2. Adaptive ℓ schedule(根据 batch KL 自动调): 收益多少?会不会让 sweet spot 漂移?
  3. 多轮 agentic RL 下,环境响应不可缓存,SPEC-RL 还能发挥多少?是否要拆 trajectory 到环境调用边界?
  4. 更大 model (32B / 70B) 上 reuse rate 是否还稳定在 50–70%?直觉上越大越稳。
  5. cold start 缓解: 第一 epoch 用 sample 的小子集 + 后续才上 SPEC-RL,实际墙钟收益?
  6. cache 写回粒度: 如果每个 step 都写回(而非每 epoch),会不会引入死循环式的低多样性?

10 · 记忆点

立场 SPEC-RL = "draft 就是上一 epoch 的我自己" 的极简 SD,没有 draft model,没有 suffix tree。
数据现象 RLVR 连续 epoch 间 token overlap 稳定在 50–70% (ROUGE-1)。这是"应该被复用"的结构性冗余。
公式 α̃ = min(1, ℓ · πcurrprev);ℓ=1 标准 SD,ℓ→∞ 全盘复用,ℓ ≈ e0.5 是论文 sweet spot。
收益 平均 2.31× rollout 加速,−66% 解码 token,准确率不掉(常 +1~2 分)。
系统 实现 = 一个 prompt → trajectory cache + 整 batch 一次 prefill verify + 短 continuation。可热插拔到 GRPO/PPO/DAPO,不改 reward / update。
关键消融 不 verify (Random Reuse): acc 37.3 → 31.4。 用 t−2 cache (Delayed): speedup 2.29× → 1.44×。verify 不能省、cache 必须实时
动力学 Verified prefix length 呈 U 形:训练前期下降 (policy 跳变)、中后期回升 (policy 趋稳)。固定 ℓ 已经够用,但 adaptive 是明显的下一步。
边界 不适用: 单 epoch 训、agentic/多轮 stochastic env、首 epoch (cold start)。
同类对比 NeMo-RL EAGLE-3 = 严格无损但要训 draft;ReSpec 介于中间;DAS/RhymeRL = 用 suffix tree 抽取更细颗粒匹配但工程重。SPEC-RL = 极简但够用。