RL每步到底慢在哪里:实测rollout占了81.5%

前言

强化学习训练链路遇到一个很实际的问题:每个 step 更新完 LoRA 后,需要先把权重保存到磁盘,再让 vLLM 加载,才能开始下一轮 rollout。

这个文件链路看起来很绕,但它真的是 RL step 的主要瓶颈吗?

当前链路

Trio 中一次新的策略版本进入采样,大致会经过:

1
2
3
4
5
6
7
Trainer GPU 上的 LoRA
→ clone 到 CPU
→ safetensors 序列化并落盘
→ 创建 SamplingRun
→ Actor 在第一次 sample 时调用 vLLM
→ vLLM 读取文件并装入 LoRA slot
→ 开始生成

先测权重刷新

测试环境使用 Qwen3.5-4B,分别测了 rank-8 和实际业务中更接近的 rank-64 LoRA。

LoRA 文件大小 warm保存完成 vLLM load 保存到首个1-token sample
rank-8 32 MB 318 ms 82~92 ms 约0.44 s
rank-64 260 MB 531 ms 255~344 ms 约0.84 s

rank-64 的 0.84 秒可以继续拆成:

1
2
3
4
5
6
Trainer实际保存               约434 ms
Trainer事件fetch等待 约100 ms
Control创建SamplingRun 约8 ms
vLLM加载 约257~280 ms
warm 1-token推理 约22 ms
SDK/Actor额外转发 约3~10 ms

如果只看权重刷新内部,耗时排序是:

1
文件生成和写入 > vLLM load > 轮询等待 > 后端交互

但这只能解释 0.84 秒由什么组成,不能说明它在完整 RL step 中很重要。

实际堵点

实际上在 rollout 的时候,需要 sample 出很长的序列。对于这种负载,前面测出来的 0.84 秒看起来是一个可以优化的固定开销,放进完整 RL step 后却只有很小的占比。

现有 OPSD 训练任务:

阶段 两轮范围 平均 Step占比
权重保存、vLLM加载与发布 0.484~0.579 s 0.532 s 1.27%
Rollout 34.236~34.269 s 34.253 s 81.54%
Forward/backward + optimizer 6.777~7.658 s 7.217 s 17.18%
完整RL step 41.597~42.416 s 42.006 s 100%

结论和最开始担心的正好相反:

1
Rollout >>> 训练 >>> 权重保存加载

权重发布平均只有 0.53 秒,占完整 step 的 1.27%

所以在当前 32×1024 的 OPSD 负载里,权重落盘和 vLLM load 并不重要

Rollout里面又是谁最慢

sample 是 rollout 的内部步骤,不能把两者的时间再次相加。

每轮会并发执行 32 个 Student sample,然后对结果计算 Teacher logprobs:

调用 单请求中位数 P95 最大值
Student sample 18.25 s 33.10 s 33.88 s
Teacher compute_logprobs 0.89 s 6.29 s 6.86 s

整个 rollout 的 wall time 是 34.25 秒,几乎和最慢的 Student sample 一样。

原因是这 32 个请求在并发执行,总耗时不是 32 个请求时间之和,而由最慢的那批生成决定:

1
rollout wall time ≈ max(student sample latency)

每轮大约生成 29456 个 tokens,实际聚合输出吞吐约为:

1
29456 / 34.25 ≈ 860 output tokens/s

最后

这次完整测试证明,长序列 RL 的实际堵点是 vLLM sample:rollout 占 81.5%,其中关键路径几乎就是最慢的 Student 生成请求。权重保存和加载只占约 1.3%,当前没有必要为了它先改整套权重传输架构。

作者

Noah Shen

发布于

2026-08-06

更新于

2026-08-06

许可协议

评论