Verl LLM 最佳实践 (DAPO + Qwen3-235B)

最后更新:11/03/2025。

目的

本指南以在 Qwen3-235B 上使用 DAPO 训练为例。我们将拆解优化目标中出现的每一个参数,将其映射到 Verl 配置条目,并分享经过实地测试的推荐设置,以便您为自己的工作负载推导出合理的设置。

Note

  1. 本指南仅涵盖重现此处讨论的 DAPO 实验所需的参数子集。如需完整列表,请参考 Verl 源代码树中的 config 组件: https://github.com/volcengine/verl/tree/main/verl/trainer/config

  2. PPO 和 GRPO 引入了 KL 约束策略。因此,我们在下面的解释中包含了该设置。您可以将此处提到的所有配置视为一个带有 KL 惩罚的 DAPO 管道。

优化目标

DAPO 目标

\[\begin{split}\begin{aligned} \mathcal{J}_{\mathrm{DAPO}}(\theta)= & \mathbb{E}_{(q, a) \sim \mathcal{D},\left\{o_i\right\}_{i=1}^G \sim \pi_{\theta_{\text {old }}}(\cdot \mid q)} \ {\left[\frac{1}{\sum_{i=1}^G\left|o_i\right|} \sum_{i=1}^G \sum_{t=1}^{\left|o_i\right|} \min \left(r_{i, t}(\theta) \hat{A}_{i, t}, \operatorname{clip}\left(r_{i, t}(\theta), 1-\varepsilon_{\text {low }}, 1+\varepsilon_{\text {high }}\right) \hat{A}_{i, t}\right)\right] } \\ \end{aligned}\end{split}\]
\[\text { s.t. } \quad 0<\mid\left\{o_i \mid \text { is_equivalent }\left(a, o_i\right)\right\} \mid<G,\]
\[\text {where} \quad r_{i, t}(\theta)=\frac{\pi_\theta\left(o_{i, t} \mid q, o_{i,<t}\right)}{\pi_{\theta_{\text {old }}}\left(o_{i, t} \mid q, o_{i,<t}\right)}, \quad \hat{A}_{i, t}=\frac{R_i-\operatorname{mean}\left(\left\{R_i\right\}_{i=1}^G\right)}{\operatorname{std}\left(\left\{R_i\right\}_{i=1}^G\right)}\]

GRPO 目标

\[\begin{aligned} \mathcal{J}_{G R P O}(\theta) & =\mathbb{E}_{q \sim P(Q),\left\{o_i\right\}_{i=1}^G \sim \pi_{\theta_{\text {old }}}(O \mid q)} \ \frac{1}{G} \sum_{i=1}^G \frac{1}{\left|o_i\right|} \sum_{t=1}^{\left|o_i\right|}\left\{\min \left[\frac{\pi_\theta\left(o_{i, t} \mid q, o_{i,<t}\right)}{\pi_{\theta_{\text {old }}}\left(o_{i, t} \mid q, o_{i,<t}\right)} \hat{A}_{i, t}, \operatorname{clip}\left(\frac{\pi_\theta\left(o_{i, t} \mid q, o_{i,<t}\right)}{\pi_{\theta_{\text {old }}}\left(o_{i, t} \mid q, o_{i,<t}\right)}, 1-\varepsilon, 1+\varepsilon\right) \hat{A}_{i, t}\right]-\beta \mathbb{D}_{K L}\left[\pi_\theta \| \pi_{r e f}\right]\right\}, \end{aligned}\]

符号说明

\((q,a)\sim D\)
  • \(D\) 表示训练数据集。对于每个样本,\(q\) 是输入提示(针对数学任务,就是问题),\(a\) 是目标输出——通常是最终答案,不包含中间推理步骤。

\(G\)
  • 组大小。对于每个提示,我们采样 \(G\) 个独立响应(即生成独立答案,以支持组内对比学习)。

\(\theta\)
  • Actor(演员)模型的参数(即策略模型的权重)。

\(\pi\)
  • 采样策略,它捆绑了 rollout 后端(如 vLLM 或 sglang)和所有生成超参数。由于 LLM 是自回归生成 token,rollout 占运行时主导,因此后端特定的调优至关重要。

\(\pi_\theta\)
  • 通过使用参数 \(\theta\) 实例化 \(\pi\) 得到的 Actor 策略。

\(\hat{A}_{i,t}\)
  • 组内第 \(i\) 个样本在时间步 \(t\) 的优势值(奖励的标准化差异,用于指导学习方向)。

\(R_i\)
  • 组内第 \(i\) 个样本分配的奖励分值。

\(\mathbb{D}_{KL}\)
  • 两个策略之间的 KL 散度(衡量策略变化程度,用于防止过度偏离原有策略)。

\(\beta\)
  • 对 KL 项加权的系数(控制 KL 约束的强度)。

\(\pi_{old}\)
  • 冻结的“旧”策略,在每处理 train_batch_size 个样本后更新。

\(\pi_{ref}\)
  • 用于计算 KL 散度的参考策略(通常是训练初始时的策略,以稳定学习过程)。

\(o_i, |o_i|\)
  • \(o_i\) 是针对第 \(i\) 个提示生成的输出序列;\(|o_i|\) 是其 token 长度。

\(\pi_\theta(o_{i,t} \mid q_i, o_{i,<t})\)
  • 在参数 \(\theta\) 下,给定提示 \(q_i\) 和之前生成的序列前缀,生成第 \(t\) 个 token 的概率。在实践中,rollout 引擎首先生成完整响应,然后为每个模型连接提示和输出;借助注意力掩码,我们可以在一次传递中计算所有 token 概率。

\(\varepsilon_{low}\)\(\varepsilon_{high}\)
  • 重要性采样(importance sampling)的下限和上限裁剪边界。DAPO 采用剪辑更高的策略,因此上限不同于下限,以防止策略更新过大。

参数参考

\((q,a)\sim D\)
  • data.train_files / data.val_files: 训练和验证数据集。它们必须以 .parquet 格式存储。使用 examples/data_preprocess 下的转换脚本,并确保您的 data_source 实现了匹配的奖励函数。您也可以复用 HuggingFace 数据集 BytedTsinghua-SIA/DAPO-Math-17k

  • data.prompt_key: 提示列名。除非您有更清晰的 schema,否则保持默认的 prompt

  • data.max_prompt_length: 提示长度的上限。设置为涵盖语料库中最长的提示;当长尾样本使其过大时,降低该值并结合 data.truncation 使用。

  • data.truncation: 超长输入的政策(从左/右截断,或引发错误)。left 对大多数运行有效。如果训练日志显示 clip_ratio 较大且指标较差,请增加 data.max_prompt_length 或清理数据。当需要严格验证时,设置为 error

\(G\)
  • actor_rollout_ref.rollout.n: 每个提示的生成数量。典型值:GRPO 为 64,DAPO 为 16。

\(\theta\)
  • actor_rollout_ref.model.path: HuggingFace 兼容格式的 Actor 模型检查点路径。

  • actor_rollout_ref.actor.megatron.use_mbridge: 当模型使用 Megatron 训练时,启用 mbridge 格式转换。使用最新的 mbridge 版本: https://github.com/ISEEKYAN/mbridge

\(\pi\)
  • actor_rollout_ref.rollout.name: Rollout 后端。Verl 目前支持 vllmsglang——根据您的基础设施进行基准测试和调优。

  • actor_rollout_ref.rollout.response_length / data.max_response_length: 生成的最大 token 数(rollout 设置优先)。较大的值可提高质量,但会消耗更多内存和延迟。监控 clip_ratio;高于 0.1 的值通常表示截断过多。

  • actor_rollout_ref.rollout.gpu_memory_utilization: Rollout 期间的目标 GPU 内存使用率。在不触发 OOM 的情况下尽可能高;启用参数/梯度/优化器卸载时,0.8–0.9 是常见值。

  • actor_rollout_ref.rollout.tensor_model_parallel_size: 推理引擎的张量并行度。确保 ``(memory_per_gpu * gpu_memory_utilization * TP) > 2 * model_parameters``(bf16/fp16)。逐步增加 TP 以扩展 KV 缓存容量,同时观察通信成本——尤其在 TP > 8 时。

  • actor_rollout_ref.rollout.temperature / top_p / top_k: Rollout 的采样调节旋钮。保持足够的随机性;temperature=1.0top_p=1.0top_k=-1 是良好的默认值。

  • actor_rollout_ref.rollout.val_kwargs.temperature / top_p / top_k / do_sample / n: 验证用的采样选项。设置 temperature > 0 以防止重复思考链。对于小型测试集(如 AIME24),提高 n``(64 是常见选择)以减少方差。实用起点是 ``temperature=1.0top_p=0.7top_k=-1do_sample=Truen=1,然后根据需要增加 n

  • +actor_rollout_ref.rollout.engine_kwargs.vllm.* / +actor_rollout_ref.rollout.engine_kwargs.sglang.*: 通过 + 语法注入的额外后端选项。请查阅后端文档获取确切语义。某些开关(如 pipeline_parallel_size)可能尚不支持;在 TP=32 时,enable_expert_parallel=True 甚至可能减慢 DeepSeek-V3 rollout,所以请仔细基准测试。

\(\pi_\theta\)
  • data.train_batch_size: 每次训练迭代的总批大小。每次 rollout 产生 train_batch_size * n 个样本。较大的值减少 rollout 次数,但增加离策略漂移(off-policy drift)。

  • actor_rollout_ref.actor.ppo_mini_batch_size: 每次优化步骤的迷你批大小。像标准深度学习工作负载一样调优它。

  • actor_rollout_ref.actor.ppo_micro_batch_size_per_gpu: 每个 GPU 组上每次前向传递处理的样本数(Megatron 组包含 TP * PP * CP 个 GPU)。保持 ≤ ppo_mini_batch_size 且尽可能大以匹配内存。

  • actor_rollout_ref.actor.use_dynamic_bsz: 启用动态批大小,以适应序列长度并提高吞吐量。

  • actor_rollout_ref.rollout.log_prob_max_token_len_per_gpu: 在动态批处理下计算对数概率时,每个 GPU 的最大 token 数。设置为至少 max_prompt_length + max_response_length 的倍数,以防止截断。

  • Megatron 并行参数(pipeline_model_parallel_size / tensor_model_parallel_size / expert_model_parallel_size / expert_tensor_parallel_size / context_parallel_size): 平衡 PP/TP/EP/ETP/CP 以匹配内存和网络约束。在 bf16/fp16 中,每个参数消耗约 2 / TP 字节;如果保留 FP32 主权重或跳过优化器卸载,则为 Adam 额外保留 4–8 字节。激活值随 micro_batch_size × sequence_length × hidden_size 缩放,可通过梯度检查点、动态批或卸载缓解。首先优先增加 TP,必要时添加 PP,通过 CP 扩展序列容量,针对 MoE 模型将 EP/ETP 与 TP 对齐,并在约束集群上保持 DP 最小,同时结合卸载。始终与硬件拓扑和通信成本对齐。

  • actor_rollout_ref.model.use_fused_kernels: 为支持的模型启用 Verl 的融合内核,以榨取额外性能。

\(\hat{A}_{i,t}\)
  • algorithm.adv_estimator: 优势估计器。针对 DAPO/GRPO,设置为 grpo

\(R_i\)
  • reward_model.reward_manager: 奖励聚合策略。DAPO 使用 dapo,GRPO 使用 naive

\(D_{KL}\)
  • algorithm.use_kl_in_reward: 是否将 KL 项添加到奖励中。PPO 为 True,GRPO 和 DAPO 为 False

  • actor_rollout_ref.actor.use_kl_loss: 是否包含 KL 损失项。PPO 为 False,GRPO 为 True,DAPO 为 False

\(\beta\)
  • actor_rollout_ref.actor.kl_loss_coef: KL 损失的权重。从 0.001 左右开始。较大的值可遏制奖励黑客化(reward hacking),但减少探索。

  • algorithm.kl_ctrl.kl_coef: 应用于奖励内的 KL 系数。根据您对散度的容忍度调整。

\(\pi_{old}\)
  • actor_rollout_ref.rollout.log_prob_use_dynamic_bsz: 当旧策略计算对数概率时,启用动态批处理。推荐。

\(\pi_{ref}\)
  • actor_rollout_ref.ref.log_prob_use_dynamic_bsz: 为参考策略启用动态批处理。推荐。

  • 参考 Megatron 并行: 将 pipeline_model_parallel_sizetensor_model_parallel_sizeexpert_model_parallel_sizeexpert_tensor_parallel_sizecontext_parallel_size 与 Actor 保持同步。

  • actor_rollout_ref.ref.megatron.param_offload: 当 Actor 卸载参数到 CPU 时,也卸载参考参数。即使没有梯度或优化器状态,对等性也有助于容量规划。

\(o_i\) / \(|o_i|\)
  • actor_rollout_ref.actor.loss_agg_mode: 损失聚合模式。Token 级 token-mean 匹配 Dr.GRPO 和 DAPO 的推荐;使用 seq-mean-token-mean 以重现原始 GRPO 行为。

\(\pi_\theta(o_{i,t} \mid q_i,o_{i,<t})\)
  • actor_rollout_ref.rollout.log_prob_micro_batch_size_per_gpu / actor_rollout_ref.ref.log_prob_micro_batch_size_per_gpu: 计算 token 概率时的批大小。Rollout 引擎生成输出,然后为每个模型拼接输入,因此平衡内存与吞吐量。

\(\epsilon_{low}\) / \(\epsilon_{high}\)
  • actor_rollout_ref.actor.clip_ratio_low / actor_rollout_ref.actor.clip_ratio_high: 重要性采样裁剪边界。针对 DAPO,使用 clip_ratio_low=0.2clip_ratio_high=0.28

vLLM 推理优化
  • actor_rollout_ref.rollout.enable_chunked_prefill: 启用分块预填充以提升 GPU 利用率(仅 vLLM)。与 max_num_batched_tokens 一起调优。

  • actor_rollout_ref.rollout.max_num_batched_tokens: 每次批的最大 token 数。实用经验法则是 max(8192, max_prompt_length + max_response_length, max_model_len);详见 vLLM 文档。

  • actor_rollout_ref.rollout.enforce_eager: 禁用 CUDA 图表。默认情况下 vLLM 利用 CUDA 图表以速度为代价额外消耗内存(不受 gpu_memory_utilization 限制);内存紧缺时设为 True

  • actor_rollout_ref.rollout.cudagraph_capture_sizes: CUDA 图表的显式捕获批大小。默认为 null;在内存受限系统上尝试 [1, 2, 4, 8, 16, 32]

优化器设置
  • actor_rollout_ref.actor.optim.lr: 学习率。从 1e-51e-6 开始。

  • actor_rollout_ref.actor.optim.lr_warmup_steps: 预热步数(例如 10)。

  • actor_rollout_ref.actor.optim.weight_decay: 权重衰减系数,通常为 0.1。

  • actor_rollout_ref.actor.optim.clip_grad: 梯度裁剪阈值,通常为 1。

  • +actor_rollout_ref.actor.optim.override_optimizer_config.optimizer_offload_fraction: CPU 上执行的优化器更新比例。大型模型如 DeepSeek 通过将其设为 1 来启用它。

  • +actor_rollout_ref.actor.optim.override_optimizer_config.overlap_cpu_optimizer_d2h_h2d / +...use_precision_aware_optimizer / +...optimizer_cpu_offload: 混合优化器的伴随开关。与 CPU 卸载一起启用。

Megatron 相关参数
  • actor_rollout_ref.actor.megatron.param_offload / optimizer_offload / grad_offload: 当 GPU 内存不足时,将参数、优化器状态和梯度卸载到 CPU。

  • +actor_rollout_ref.actor.megatron.override_transformer_config.recompute_method / recompute_granularity / recompute_num_layers: 梯度检查点控制。启用(例如 uniformfull1)以用计算换取内存。

  • +actor_rollout_ref.actor.megatron.override_transformer_config.moe_router_dtype / moe_shared_expert_overlap / moe_permute_fusion / moe_enable_deepep / moe_token_dispatcher_type: 推荐的 MoE 开关(示例值:fp32FalseTrueTrueflex)以实现稳定性能。

  • +actor_rollout_ref.actor.megatron.override_transformer_config.gradient_accumulation_fusion: 启用融合梯度累积以获取额外加速。

  • +actor_rollout_ref.actor.megatron.override_transformer_config.account_for_embedding_in_pipeline_split / account_for_loss_in_pipeline_split / num_layers_in_last_pipeline_stage: 当层数不能均匀划分时的管道并行调整。将嵌入和损失视为独立阶段,当需要手动控制时设置 num_layers_in_last_pipeline_stage``(0 ``${LAST_LAYER})。

训练器
  • trainer.logger: 日志后端。在 Volcano Engine ML Platform 上使用 ['console', 'wandb']['console', 'vemlp_wandb']

  • trainer.project_name / trainer.experiment_name: 项目和实验的层次命名,以便快速定位运行。

  • trainer.n_gpus_per_node / trainer.nnodes: 每个节点和总节点数的 GPU 数量。与您的集群分配匹配。

  • trainer.test_freq / trainer.save_freq / trainer.total_epochs: 评估间隔、检查点间隔和总轮数——根据您的 SLA 配置。

  • trainer.log_val_generations: 日志中存储的验证样本数。从 10 开始,根据需要调整。

  • trainer.val_before_train: 当您需要一个基准检查点时,在训练开始前运行验证。