跳转至

VeRL Async

导言

异步 RL 的核心不是简单“并行化 PPO”,而是把 rollout、reward / logprob、训练更新和参数同步之间的同步屏障拆成可控队列与版本语义。它用 bounded staleness 换取更高 E2E throughput,但必须同时回答 old logprob 一致性、policy lag、partial rollout、样本丢弃和复现实验的问题。

RL 异步流水示意

自绘示意图。同步 RL 最大的问题不是某个 kernel 慢,而是 rollout 长尾、reward、logprob 和 update 之间互相等待。

同步瓶颈

同步 PPO / GRPO 流程通常像这样:

step N:
  rollout -> reward -> old/ref logprob -> advantage -> update actor -> step N+1

这个流程语义清楚,debug 简单,但会产生明显 stage bubble:

  • rollout 长尾样本拖住训练。
  • reward 服务慢时训练卡等待。
  • actor update 时 rollout 资源空闲。
  • 权重同步前后有全局屏障。

异步训练试图把这些等待变成队列和版本控制问题:rollout 继续生产,trainer 持续消费,参数按规则同步,而不是每个 step 都全局对齐。

异步不是免费午餐

异步减少等待,但会引入 policy lag。只看 wall-clock speedup 而不记录 stale sample ratio、policy version gap 和 old logprob 来源,无法判断收益是否可靠。

FullAsync 架构

verl 的 Fully Async Policy Trainer 把系统拆成四个角色:1

组件 职责
Rollouter 逐样本生成 rollout,并写入 MessageQueue
MessageQueue 缓冲 rollout 样本,隔离生产与消费速度
Trainer 按 batch 消费样本并做本地 update
ParameterSynchronizer 将 Trainer 参数同步给 Rollouter

官方文档报告,在 128 GPUs 上训练 Qwen2.5-7B 时,FullAsync 相比同步 baseline 取得 2.35x 到 2.67x 性能提升,且未显著影响结果。1

核心参数

FullAsync 的关键不是一个布尔开关,而是一组 freshness 控制:

参数 含义 风险
async_training.require_batches Trainer 一次取多少个 ppo_mini_batch_size 后训练 太小可能分布不稳,太大又增加等待
async_training.trigger_parameter_sync_step 做多少次本地 update 后同步 Rollouter 过大时 policy lag 增大
async_training.staleness_threshold 允许使用多少比例 stale samples 过大时 KL 和 response length 易抖
async_training.partial_rollout 参数同步时是否打断并恢复未完成 rollout 需要准确记录 partial span
actor_rollout_ref.actor.use_rollout_log_probs 是否使用 rollout 生成的 old logprob 关系到 PPO/GRPO ratio 语义

官方文档里 staleness_threshold=0 表示严格同步;当 rollouter 足够快时,staleness_threshold=1 接近 one-step off-policy,但文档建议小于 1。1

四种模式

on-policy pipeline

trigger_parameter_sync_step=1
staleness_threshold=0

语义最清楚,Rollouter 生成一个训练批次后 Trainer 训练,然后同步参数。长尾等待仍然明显。

stream off-policy pipeline

trigger_parameter_sync_step>1
staleness_threshold=0

Rollouter 一次生产多个 mini-batch,Trainer 多次本地 update 后再同步。它减少了局部空泡,但仍不允许 stale samples。

async stream with stale samples

staleness_threshold>0
partial_rollout=False

同步后仍允许消费一部分旧参数生成的样本。收益来自更少等待,风险来自 off-policy 偏差。

async stream with partial rollout

staleness_threshold>0
partial_rollout=True

参数同步时可以打断仍在生成的样本,同步后继续生成。它进一步减少等待慢样本的 idle time,但要求日志记录 partial rollout ratio 和 max partial span。

横向比较

异步 RL 系统收益对比

根据公开文档和论文整理。不同系统的模型、硬件、任务和指标不同,只能用于判断方向和量级,不能直接排名。

AsyncFlow 把异步 RL 的数据系统能力进一步抽象出来,中心是面向 RL 多任务流的 TransferQueue:producer / consumer 只读写自己关心的字段,控制器维护 metadata,训练侧可以像 DataLoader 一样消费 ready samples。论文报告平均 1.59x throughput improvement。2

AReaL 关注 generation 与 training fully decoupled,并提出 staleness-aware training / decoupled PPO。论文报告最高约 2.57x 训练加速。3

StreamRL 关注 disaggregated stream generation,让 completed samples 以 stream 方式进入训练,并结合 length-aware / skew-aware 调度。论文报告最高 2.66x throughput 和最高 1.33x cost-effectiveness。4

这些工作共同说明:异步收益主要来自减少 stage idle,而不是提高单个 kernel 的算力效率。

正确性风险

异步训练必须把样本和版本绑定起来:

  • old logprob:必须对应生成该 response 的行为策略。
  • policy version gap:每条样本应记录 rollout policy 和 update policy 的差距。
  • stale sample ratio:要统计实际被训练消费的 stale 样本比例。
  • partial rollout:要记录同一 trajectory 是否跨越多个 policy version。
  • drop / retry:队列满、reward 失败或 rollout timeout 时不能静默改变数据分布。

old logprob 是语义锚点

在异步设置里,old logprob 最好随 rollout 一起生成或显式记录来源。否则 Trainer 后算 old logprob 时很容易误用当前参数,把 off-policy 样本伪装成 on-policy 样本。

验证指标

层次 指标 目的
系统 samples/s、tokens/s、step/hour、stage idle ratio 判断是否真的减少等待
队列 queue depth、drop count、message latency 判断 backpressure 是否健康
同步 parameter sync latency、sync interval 判断参数同步是否成为新瓶颈
算法 policy version gap、stale sample ratio、KL、clipfrac、entropy 判断 off-policy 影响是否可控
结果 reward / accuracy wall-clock 曲线 判断是否更快达到目标分数

实践顺序

  1. 同步 baseline:记录每个 stage 的耗时和 idle ratio。
  2. stream off-policy:先保持 staleness_threshold=0,只减少局部空泡。
  3. 小 staleness:逐步提高 threshold,通常先小于 1。
  4. partial rollout:只在长尾明显且 metadata 完整时开启。
  5. 组合 TransferQueue:当数据搬运和 controller 成为瓶颈时,再引入数据系统层解耦。

总结

FullAsync、AsyncFlow、AReaL 和 StreamRL 的共同目标是减少 RL 后训练的端到端等待。但异步不是越多越好,真正要控制的是 bounded staleness:样本可以旧一点,但旧到什么程度、来自哪个 policy、old logprob 怎么算、训练曲线是否稳定,都必须可观测。

参考文献

评论