Best Practices of Reinforcement Learning with verl
Best Practices of Reinforcement Learning with verl
Liwei Ma, Yan Bai, DevTech China | NVIDIA AI Open Day, Nov. 7th, 2025
议程 (Agenda)
- Verl 和 VLM 概览
- 关键问题与解决方案
- Verl 中的高级优化
- 总结与要点
1. Verl 和 VLM 概览
LLM RL 及近期进展
-
角色: 强化学习 (RL) 是语言模型主要的后训练 (post-training) 实践。
- 对齐 (Align) 与推理 (reasoning)
- 从开源模型到商业应用的必要步骤
-
算法: 反馈设计是设计强化学习系统的关键。
- 基于奖励 (Reward-based)、无奖励 (reward-free)、基于规则 (rule-based) 和连续环境反馈
-
工程: GPU 效率是一个持续的目标。
- SPMD (单程序多数据)、负载均衡、异步协程、单步 off-policy、部分 rollout
-
模型与应用:
- LLM, Vision-Language-Model (VLM), Vision-Language-Action (VLA)
- 数学, STEM, 编程, Agent, 多模态任务, 多智能体系统, 机器人, 医疗
Verl 当前内部架构与工作流
- 一个基于 Ray 的强化学习框架,在 NVIDIA GPU 上具有领先性能。
-
调度两个引擎: 在同一组 GPU 上进行 rollout 和训练。
- Rollout 引擎: vLLM, SGLang, Trtllm (待集成)
- 训练引擎: FSDP, Megatron-core
-
两个工作流阶段:
- 加速 rollout
- 加速训练
- 加速转换过程
verl 的用户界面
verl 的用户界面位于 verl/trainer/config 路径下,其主要特点如下:
- 基于 Hydra 和 yaml 的层级化配置。
-
算法支持最新的进展:
- PPO, GRPO, GSPO, ReMax, RLOO, PRIME, DAPO/DrGRPO, REINFORCE++, recipe
-
Actor_rollout_ref and critic
- 训练: Actor, critic
- 推理: ref
- Rollout: rollout
- Nsight 系统性能分析器
- 训练基础设施配置:
- 数据, 模型, 训练器
模型:Qwen 2.5 VL,数据集:geometry3k
-
Qwen 2.5 VL 模型包含3种类型的层
- VIT: 32 层
- Merger: 2 层
- LLM: 28 (7B), 80 (72B)
-
3002 个几何问题
- 选择题,答案由规则确定
- 示例
2. 关键问题与解决方案
RL 的关键步骤和问题
下图展示了实施强化学习的流程及其中的关键问题:
- 定义业务目标: 更高的推理智能,展示更多优化机会。
- 选择数据集和模型: 数据整理,工具格式,基础模型能力。
- 验证算法和工作流: 算法选择 (GRPO, DAPO, ...),RL工作流是否就绪,Nsight系统检查。
- 扩展到业务模型/适配GPU: 资源估计,内存估计。
- 找到正确的并行策略: Rollout, Training (TP, PP, VPP, CP, EP, ETP, DP)。
- 覆盖引擎细节特性: 动态批处理,卸载参数,固定视觉部分。
使用 Nsight System 理解工作负载
- Profiler 工具:
nsys - Profiler 配置:
Profiler.steps: [1,2, 5], null, []Profiler.continuous_steps=True, FalseProfiler.nsys.discrete=False, TrueActor.profiler_enable: TrueActor.all_ranks: True; ranks: [1,2]
通过 Nsight System 的时间线视图,可以清晰地分析各个阶段的耗时,例如 generation(生成)、reward(奖励计算)、update_actor(Actor 更新),以及各个步骤(Step 1, Step 2 等)和开销(overhead)。
verl 执行模型 (on-policy)
从资源和计算角度看:
- 在同一组 GPU 上连续执行步骤(引擎或服务器模式)。
- 工作规模: 一个步骤处理一批 prompts。
- 不同的并行策略 应用于 Rollout 和训练阶段(resharding weights)。
- Rollout 策略: 单批次,连续批处理,DP 间的负载均衡。
- 训练策略: mini batch, micro batch, 负载均衡, 动态批处理。
下表展示了在 Hopper 80G 上的典型时序:
| 7b (n1) | 32b (n4) | 72b (n8) | |
|---|---|---|---|
| Step | 160 | 165 | 170 |
| rollout | 60 | 55 | 70 |
| training | 50 | 60 | 60 |
实验总结
下图展示了基于 Qwen 模型的实验设置和结果。
实验配置:
| 配置项 | 值 |
|---|---|
| Model | Qwen 2.5/3 VL |
| Model Size | 7b, 32b, 72b |
| GPUs | 8, 32, 64 |
| algorithm | GRPO, DAPO |
| Training engine | FSDP, Mcore |
| Rollout engine | vLLM |
| Rollout parallelism | Valid space |
| Training parallelism | Valid space |
| Offload parameters | Yes/No |
| Dynamic batching (training) | Yes/No |
| Fixed vision | Yes/No |
性能曲线:
右图展示了前10次运行的 critic/score/mean 随训练步骤的变化。图中比较了不同模型大小(如 Qwen 3 30b, Qwen 2.5 72b, Qwen 2.5 32b, Qwen 2.5 7b)和算法(DAPO)的性能。
GRPO vs DAPO 对比 (Qwen2.5 VL 7b fsdp vllm)
- DAPO 基于 GRPO:
- 移除了参考模型 (reference model)
- 采用了动态采样 (dynamic sampling)
算法特性对比:
| PPO | GRPO | DAPO | |
|---|---|---|---|
| Models | 4 | 2 | 1 |
| Rollout/prompt | low | medium | high |
| Computation | medium | medium | high |
| Static Memory | high | medium | low |
配置差异:
| Config | GRPO | DAPO |
|---|---|---|
| entry | verl/ppo | recipe/dapo |
| train_batch_size | 512 | 512 |
| gen_batch_size | 512 | 512*3 |
| rollout.n | 5 | 16 |
| adv_estimator | grpo | grpo |
| actor.use_kl_loss | True | False |
| kl_ctrl.kl_coef | 0.001 | 0 |
| filter_groups | Disable | Enable |
| Nnodes | 1 | 1,4 |
从右侧的图中可以看出,DAPO n1 在 Reward 上显著优于 GRPO n1,并且在 Timing step 和 Timing generation 方面也表现出更优的性能。
将大模型适配到 GPU 资源:内存估计 (Qwen 3 VL 30B)
- Megatron Memory Estimator v0.13
- 探索在大模型训练中使用 Megatron-Core 训练框架来提高内存使用效率。
-
静态内存消耗 = 固定的 + 可共享的 / 并行
- TP, PP, CP, EP, ETP
-
动态内存消耗 = 变量 * 线性参数
ppo_micro_batch_size(训练, 静态批大小)ppo_max_token_len_per_gpu(训练, 动态批大小)max_num_batched_tokens(rollout)
-
重计算 以时间换取内存。
- 静态成本 (rollout)
rollout_gpu_memory_utilization
vLLM 探索 (32b 4 nodes, fsdp, rollout TP=2, 4, 8, 16, Hopper 80G)
- 比较 rollout TP(张量并行)= 4, 8
- 步长时间差异:生成(gen) 30s,训练(training) 25s,转换(transition) 5s
- 技巧: 尝试使用更小的 TP 以获得更大的 DP(数据并行)
TP 与 kvcache 关系表:
| TP | 2 | 4 | 8 | 16 |
|---|---|---|---|---|
| kvcache | 0.5 | 0.5 | 0.5 | |
| OOM | valid | valid | invalid |
右侧的图表展示了不同 TP 设置下(TP=8 vs TP=4)的 timing_s/gen, timing_s/update_actor, 和 timing_s/step 的性能曲线。
FSDP 探索 (Base vs fix-vision, dynamic-batch-size, rollout engine/server vs all, 32B)
-
技巧: 如果内存充足,可以关闭 FSDP 的参数和优化器卸载(offload)。
fsdp_config.param_offloadfsdp_config.optimizer_offload
-
动态批大小 在本案例中会降低性能。
- 需要使用 Nsight 进行深入分析。
下图展示了 timing_s/gen 和 timing_s/step 在不同配置下的性能曲线,比较了开启和关闭动态批大小,以及关闭卸载(offload)后的性能表现。结果显示,关闭 offload 可以获得最佳性能。
FSDP 动态批次大小分析
- 在 Nsight 时间线中发现了 GPU 的低效问题。
- 下图展示了整体时间线(上)和其中一个间隙的放大视图(下)。时间线中的空白间隙表明 GPU 在某些时间段内处于空闲状态,从而导致效率低下。
Megatron-Core 并行性探索
本节探讨了在 Qwen3 VL 30B 模型中,不同张量并行(TP)和专家并行(EP)设置对性能的影响(TP=1, 2, 4, EP=4, 8)。
- 性能观察:在此案例中,性能随着张量并行(TP)规模的减小而提升。
- 建议:尝试使用较小的 TP。
- 实验设置:
- TP: 1, 2, 4
- EP: 4, 8
下图展示了不同并行策略下的 timing_s/gen, timing_s/step 和 timing_s/update_actor 指标。右侧的 timing_s/update_actor 图表清晰地表明,TP1+EP8+recompute 配置的执行时间最短,性能最优。
Megatron-Core 微调
本节分析了在微调过程中,重计算(Recompute)策略在性能和内存占用之间的权衡。
- 发现:在此案例中,
TP2(不使用重计算)和TP1+recompute(使用重计算)获得了相似的性能。 - 建议:当遇到内存不足(OOM)问题时,可以尝试启用重计算。
- 实验设置:
- TP: 1, 2, 4
- EP: 8
- Recompute: yes, no
下图左侧的 timing_s/update_actor 图表显示 TP2 和 TP1+recompute 的性能(执行时间)相近。右侧的 perf/max_memory_allocated_gb 图表则显示,TP1+recompute 的峰值内存分配显著低于 TP2,这验证了重计算以计算换取内存的有效性。
性能优化指南
以下是进行性能优化的通用指南:
-
将问题规模适配到一小组 GPU 中
- 通过内存估算器进行初始设置。
-
建立经验模型
- 结果 = 变量 * 线性参数 + 偏差
- 结果 = 可共享成本 / 并行参数 + 偏差
-
进一步覆盖引擎的详细参数
3. Verl 中的高级优化
长尾数据训练中的工作负载均衡
- 问题:强化学习(RL)数据集包含可变长度的序列,这在训练过程中带来了显著的效率挑战。
- RL 数据集的序列长度呈现偏斜的长尾分布。
- 结果:导致 GPU 在内存和计算效率方面都存在利用率不足的问题。
下图展示了典型的长尾序列长度分布情况。
数据并行中的不平衡
- 在没有序列打包(Packing)或动态批处理(Dynamic Batching)的情况下,数据并行(DP)会因工作负载不均而出现效率问题。
- 实验设置:GRPO Qwen2.5-7B, DP=4, PP=2。
- 问题:数据并行(DP)的同步点需要等待最慢的 rank(掉队者)完成计算。
下图的时间线显示,不同 rank 的计算时间不同,部分 rank 会提前完成并进入等待状态(例如 Rank 2),造成 GPU 空闲。
流水线并行中的不平衡
- 在没有序列打包或动态批处理的情况下,流水线并行(PP)同样会因工作负载不均而产生“气泡”(Bubbles),即 GPU 空闲时间。
- 实验设置:GRPO Qwen2.5-7B, DP=4, PP=2。
下图展示了两个设备在流水线并行执行时,由于各 micro-batch 的处理时间不同而产生的空闲气泡。
解决方案
为了解决工作负载不均衡问题,提出了以下解决方案:
-
Inter DP (数据并行组间):
- 采用感知工作负载的数据并行切分,综合考虑了注意力机制的二次方复杂度和前馈网络(FFN)的线性复杂度。
-
Intra DP (数据并行组内):
- 采用感知工作负载的动态批处理,以均衡各个 micro-batch 间的工作负载。
- 对 micro-batch 进行排序,使得连续的批次具有相似的工作负载。
- 将较小的 micro-batch 放置在流水线的两端,以减少预热(warm-up)和冷却(cool-down)阶段产生的气泡。
下图详细展示了“排序动态批处理”(Sorted Dynamic Batching)的机制,通过对 micro-batch 重新排序来优化流水线执行效率。
性能
本节展示了负载均衡解决方案的性能提升效果。
- 实验设置:使用 8 卡 Hopper 80G GPU 训练 GRPO 7B 模型。
- 下图比较了开启均衡(_Balance)和未开启均衡的性能(以 mfu/actor 指标衡量)。结果表明,无论是 TP4DP2 还是 TP2DP4 配置,
_Balance版本都获得了显著更高的模型 FLOPs 利用率(MFU),证明了该方法的有效性。
多轮对话与智能体学习:通过 Agent-loop 实现
- 为了训练具备智能体(agent)和工具调用能力的强大语言模型(LLM),
agent-loop提供了一套标准 API,用于实现多轮对话和带工具的智能体式推演(rollout)。 -
用途包括:
- 调用 LLM 生成 API
- 调用工具:
- 网页搜索
- 数据库查询
- 代码沙箱
- 环境交互
-
核心流程:
prompt输入到Agent Loop,Agent Loop与LLM交互生成结果,最终产生output。
用例
-
A. ReTool:代码沙箱
- 下图展示了 ReTool 的强化学习训练框架。它包含一个策略 LLM 与代码沙箱进行交互,通过交叉执行代码和基于文本的强化学习进行训练。
-
B. DeepEyes:image_zoom_in_tool
- 下图展示了一个视觉智能体的案例。当被问及“外套是黑色的吗?”,智能体首先进行思考,然后调用
image_zoom_in_tool工具放大图像的关键区域,进行再次检查后,得出“外套是红色的”这一更准确的结论。
- 下图展示了一个视觉智能体的案例。当被问及“外套是黑色的吗?”,智能体首先进行思考,然后调用
为实现最佳吞吐量进行异步训练
- 随着输出序列长度的增加,推演(rollout)引擎会受到长尾输出的影响,导致效率下降。
- 为了更好地利用 GPU,我们生成用于未来步骤的样本(n-step-off policy)。
- 如果某些序列的计算只完成了一半,我们会中断生成过程,在下一次权重更新后继续(部分推演,partial rollout)。
下图展示了异步训练的架构,包括 ActorRolloutRef、Rollouter、MessageQueue 和 Trainer,实现了数据生成与模型训练的并行化。
此部分由美团搜索团队贡献。
异步训练模式
下图展示了四种不同的异步训练流水线模式:
- (a) on policy pipeline (在策略流水线)
- (b) stream off policy pipeline (流式离策略流水线)
- (c) async stream pipeline with staleness samples (带陈旧样本的异步流式流水线)
- (d) async stream pipeline with partial rollout (带部分推演的异步流式流水线)
这些模式在 Rollouter 和 Trainer 的同步方式、数据新鲜度等方面有所不同。
此部分由美团搜索团队贡献。
- (b) 流式离策略(stream off policy)流水线
- 在此模式下,
Trainer(训练器)在开始处理第一批mini-batch之前,需要等待Rollouter(部署器)完成第一批次(batch)的部署(rollout)。 - 同样,
Rollouter在开始新一批次的处理前,需要等待Trainer完成上一批次的最后一个mini-batch的训练。 - 这种方式在部署和训练之间存在明确的同步等待点,确保数据按批次顺序处理。
- 在此模式下,
- (c) 带有过时样本(staleness samples)的异步流式流水线
- 此模式引入了更强的异步性。
Trainer的处理不再严格等待批次的开始或结束,而是等待活动任务完成(wait active task finish)。 MessageQueue(消息队列)中可能会包含一些过时的数据(图中红色部分),这些数据由较早的模型版本生成,但仍被用于训练。- 这种方法减少了等待时间,从而提高了整体吞吐量,但可能会引入因使用过时数据而导致的训练不稳定性。
- 此模式引入了更强的异步性。
- (d) 带有部分部署(partial rollout)的异步流式流水线
- 在此模式中,
Rollouter可以生成部分数据(图中橙色部分)并将其送入MessageQueue,而无需等待整个批次完成。 - 这使得
Trainer可以更早地开始处理数据,进一步减少了空闲时间,最大化了组件的并行度。 - 这种流水线设计旨在通过重叠计算和数据生成来达到最高的系统效率。
- 在此模式中,
性能
- 在H20上使用7B模型的DAPO性能
- 下表展示了不同配置下同步与全异步策略的性能对比。实验在32、64和128个GPU资源分配下进行。
colocate sync:同步训练模式。fully_async_policy:全异步训练策略。- 结果显示,
fully_async_policy在所有资源配置下都显著缩短了训练总时间,实现了高达2.67倍的加速。例如,在128个GPU上,完成400步训练,同步模式需要1天16小时48分钟,而异步模式仅需17小时22分钟(加速比2.35倍)。 - 异步策略在提高吞吐量的同时,也保持了相当的准确率(
acc/mean@1),尽管最终的last值略有下降,但最大值max仍然具有竞争力。
4. 总结与要点
总结与要点 (Takeaways)
- 遵循Verl提供的丰富示例。
- 利用Nsight-System定位性能瓶颈。
-
采用Megatron作为训练后端,以获得最佳的训练MFU(模型浮点运算利用率)。
- 使用内存估算器找到最佳的并行化和重计算设置。
-
使用工作负载感知的动态批处理(dynamic batching)来减轻长尾数据分布的不平衡效应。
- 考虑使用带有工具调用(tool calling)的多轮次智能体(multi-turn agentic)训练,通过agent-loop实现。
- 社区支持:
- 尝试异步训练以获得最佳吞吐量。