VeRL Async
同步瓶颈
同步 PPO / GRPO 流程通常像这样:
1 | step N: |
这个流程语义清楚,debug 简单,但会产生明显 stage bubble:
- rollout 长尾样本拖住训练。
- reward 服务慢时训练卡等待。
- actor update 时 rollout 资源空闲。
- 权重同步前后有全局屏障。
异步训练试图把这些等待变成队列和版本控制问题:rollout 继续生产,trainer 持续消费,参数按规则同步,而不是每个 step 都全局对齐。
FullAsync 架构
verl 的 Fully Async Policy Trainer 把系统拆成四个角色:[^verl-fullasync]
| 组件 | 职责 |
|---|---|
| Rollouter | 逐样本生成 rollout,并写入 MessageQueue |
| MessageQueue | 缓冲 rollout 样本,隔离生产与消费速度 |
| Trainer | 按 batch 消费样本并做本地 update |
| ParameterSynchronizer | 将 Trainer 参数同步给 Rollouter |
官方文档报告,在 128 GPUs 上训练 Qwen2.5-7B 时,FullAsync 相比同步 baseline 取得 2.35x 到 2.67x 性能提升,且未显著影响结果。[^verl-fullasync]
核心参数
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。[^verl-fullasync]
四种模式
on-policy pipeline
1 | trigger_parameter_sync_step=1 |
语义最清楚,Rollouter 生成一个训练批次后 Trainer 训练,然后同步参数。长尾等待仍然明显。
stream off-policy pipeline
1 | trigger_parameter_sync_step>1 |
Rollouter 一次生产多个 mini-batch,Trainer 多次本地 update 后再同步。它减少了局部空泡,但仍不允许 stale samples。
async stream with stale samples
1 | staleness_threshold>0 |
同步后仍允许消费一部分旧参数生成的样本。收益来自更少等待,风险来自 off-policy 偏差。
async stream with partial rollout
1 | staleness_threshold>0 |
参数同步时可以打断仍在生成的样本,同步后继续生成。它进一步减少等待慢样本的 idle time,但要求日志记录 partial rollout ratio 和 max partial span。
横向比较
AsyncFlow 把异步 RL 的数据系统能力进一步抽象出来,中心是面向 RL 多任务流的 TransferQueue:producer / consumer 只读写自己关心的字段,控制器维护 metadata,训练侧可以像 DataLoader 一样消费 ready samples。论文报告平均 1.59x throughput improvement。[^asyncflow]
AReaL 关注 generation 与 training fully decoupled,并提出 staleness-aware training / decoupled PPO。论文报告最高约 2.57x 训练加速。[^areal]
StreamRL 关注 disaggregated stream generation,让 completed samples 以 stream 方式进入训练,并结合 length-aware / skew-aware 调度。论文报告最高 2.66x throughput 和最高 1.33x cost-effectiveness。[^streamrl]
这些工作共同说明:异步收益主要来自减少 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 时不能静默改变数据分布。
验证指标
| 层次 | 指标 | 目的 |
|---|---|---|
| 系统 | 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 曲线 | 判断是否更快达到目标分数 |
实践顺序
- 同步 baseline:记录每个 stage 的耗时和 idle ratio。
- stream off-policy:先保持
staleness_threshold=0,只减少局部空泡。 - 小 staleness:逐步提高 threshold,通常先小于 1。
- partial rollout:只在长尾明显且 metadata 完整时开启。
- 组合 TransferQueue:当数据搬运和 controller 成为瓶颈时,再引入数据系统层解耦。
总结
FullAsync、AsyncFlow、AReaL 和 StreamRL 的共同目标是减少 RL 后训练的端到端等待。但异步不是越多越好,真正要控制的是 bounded staleness:样本可以旧一点,但旧到什么程度、来自哪个 policy、old logprob 怎么算、训练曲线是否稳定,都必须可观测。
参考文献
[^verl-fullasync]: verl Fully Async Policy Trainer documentation.
[^asyncflow]: Zhenyu Han et al., AsyncFlow: An Asynchronous Streaming RL Framework for Efficient LLM Post-Training, arXiv, 2025.
[^areal]: AReaL: A Large-Scale Asynchronous Reinforcement Learning System for Language Reasoning, arXiv, 2025.
[^streamrl]: StreamRL: Scalable, Heterogeneous, and Elastic RL for LLMs with Disaggregated Stream Generation, arXiv, 2025.