
verl 分布式 RL 训练常见问题排查指南Ray、Slurm、安装、精度与性能调试全解析【免费下载链接】verlverl/HybridFlow: A Flexible and Efficient RL Post-Training Framework项目地址: https://gitcode.com/GitHub_Trending/ve/verl导读本文基于 verl 官方 FAQdocs/faq/faq.rst整理而成聚焦 verl 在分布式强化学习后训练中最高频的故障场景Ray 分布式调试与 CPU 注册问题、Slurm 集群上的多节点运行、Linux-arm64 平台安装报错、Triton 即时编译失败、Checkpoint 格式转换、batch size 概念辨析、Ray Timeline 性能分析、wandb 专用代理以及推理与训练序列精度不一致actor/grad_norm 持续升高的定位与解决。文中每个问题均结合当前仓库源码与配置如verl/trainer/config/ppo_trainer.yaml、verl/workers/config/actor.py、examples/tutorial/slurm/ray_on_slurm.slurm进行佐证读者可按图索骥快速定位并修复实际训练中的问题。Ray 相关如何在分布式 Ray 环境下加断点调试verl 的所有 workerActor、Critic、Rollout、Reward Manager 等都运行在 Ray 分布式环境中直接使用pdb会因进程不在同一终端而失效。官方建议参考 Ray 提供的分布式调试指南ray-distributed-debugger文档其核心思路是在需要断点的地方调用 Ray 的分布式调试 API如ray.util.pdb.set_trace()或breakpoint()配合 Ray 的调试工具通过 Ray 的调试会话连接到远端 worker 进程进行交互式单步调试。需要注意的是该功能依赖 Ray 的调试依赖包ray[debug]/ debugpy在部署到生产集群前建议先在单机上验证调试链路可用。“Unable to register worker with raylet” 如何解决报错现象Ray 集群启动时 worker 进程无法向 raylet 注册导致训练任务挂起或崩溃。根本原因该问题通常源于系统层面的 CPU 共享限制。例如 SLURM 集群会对节点上 CPU 的使用方式施加约束而ray.init()默认会按照机器的 CPU 核心数尽量多地启动 worker 进程SLURM 的约束导致这些core-workers看不到raylet进程从而注册失败。解决方法在训练配置中显式设置ray_init.num_cpus将其限制为系统允许的 CPU 数量ray_init.num_cpus16从仓库源码看verl/trainer/config/ppo_trainer.yaml中ray_init段的num_cpus默认值为null即“使用全部 CPU”verl/trainer/config/evaluation.yaml中的注释也明确指出“None表示使用所有 CPU在 SLURM 等受限系统中可能导致挂起请设置为允许的数量”。在多节点或 SLURM 环境下运行时务必显式设置该参数。分布式训练如何用 Ray 运行多节点后训练任务verl 本身不负责启动跨节点集群而是复用 Ray 作为底层调度层。标准做法是按 Ray 官方文档Ray Core 的 starting-ray 指南启动一个 Ray 集群并提交 Ray job在 verl 的训练配置中将trainer.nnodes设置为任务所需的机器数量。例如两个节点、每节点 8 卡trainer.nnodes2 trainer.n_gpus_per_node8在verl/trainer/config/ppo_trainer.yaml中trainer段的默认值为nnodes: 1、n_gpus_per_node: 8main_ppo.py会据此计算总 GPU 数并初始化 Ray 资源。如何在 SLURM 管理的集群上使用 verlRay 官方提供了在 SLURM 之上启动 Ray 集群的教程Ray Clusters 的 Slurm 用户指南。verl 仓库已在多节点 SLURM 集群上验证了 GSM8K 示例 的完整流程具体步骤如下第 1 步可选准备容器环境如果集群支持 Apptainer 或 Singularity 且你希望使用容器可将 verl 的 Docker 镜像转换为 Apptainer 镜像否则也可用集群上的包管理器直接搭建环境或借助 SLURM 的 OCI 支持使用其他容器运行时apptainer pull /your/dest/dir/vemlp-th2.4.0-cu124-vllm0.6.3-ray2.10-te1.7-v0.0.3.sif \ docker://verlai/verl:vemlp-th2.4.0-cu124-vllm0.6.3-ray2.10-te1.7-v0.0.3第 2 步准备数据集与模型权重按照 GSM8K 示例 的说明准备训练数据train.parquet / test.parquet与模型 checkpoint。第 3 步修改 SLURM 作业脚本编辑仓库自带的 examples/tutorial/slurm/ray_on_slurm.slurm替换为你集群的实际信息包括#SBATCH头部的分区--partition、账户--account、节点数--nodes、每节点 GPU 数--gpus-per-node等资源规格脚本内的verl_workdir、train_files、val_files、apptainer_image_path等路径变量可选在多网卡集群上通过RAY_NETWORK_INTERFACEib0 sbatch ray_on_slurm.slurm将 Ray 绑定到指定网卡。该脚本的核心逻辑是利用scontrol show hostnames解析节点列表在头节点上以ray start --head启动 Ray 头节点随后遍历其余节点以ray start --address逐个加入 worker 节点最后在头节点上运行python3 -m verl.trainer.main_ppo并将trainer.n_gpus_per_node、trainer.nnodes分别取自SLURM_GPUS_PER_NODE与SLURM_NNODES环境变量保证 verl 看到的资源与 SLURM 分配一致。第 4 步提交作业sbatch ray_on_slurm.slurm注意事项不同 SLURM 集群的配置差异较大遇到问题请对照 Ray 的 SLURM 用户指南排查常见陷阱。若修改了 SLURM 的资源规格务必同步更新作业脚本中的环境变量如 CPU/GPU 数量否则 Ray 与 SLURM 之间的资源视图不一致会引发注册或调度问题。安装相关NotImplementedError: TensorDict does not support membership checks with theinkeyword错误信息NotImplementedError: TensorDict does not support membership checks with the in keyword. If you want to check if a particular key is in your TensorDict, please use key in tensordict.keys() instead.问题原因linux-arm64平台上没有合适的tensordict版本可供安装。可通过如下命令确认pip install tensordict0.6.2典型的输出如下注意可用版本列表中缺失 0.6.x 系列ERROR: Could not find a version that satisfies the requirement tensordict0.6.2 (from versions: 0.0.1a0, 0.0.1b0, 0.0.1rc0, 0.0.2a0, 0.0.2b0, 0.0.3, 0.1.0, 0.1.1, 0.1.2, 0.8.0, 0.8.1, 0.8.2, 0.8.3) ERROR: No matching distribution found for tensordict0.6.2解决方案一从源码安装 tensordictpip uninstall tensordict git clone https://github.com/pytorch/tensordict.git cd tensordict/ git checkout v0.6.2 python setup.py develop pip install -v -e .解决方案二临时规避直接修改出错位置的代码将tensordict_var改为tensordict_var.keys()从而用in检查 keys 集合而非 TensorDict 本身。此方法仅用于临时绕过升级或正确安装 tensordict 后应恢复原代码。Illegal memory access非法内存访问如果在 rollout 阶段遇到类似CUDA error: an illegal memory access was encountered的错误请对照你所使用的 vLLM 版本查阅 vLLM 官方文档中的故障排查步骤。这类错误通常与 vLLM 的 CUDA kernel、显存越界或驱动版本相关需要结合具体 vLLM 版本的已知问题处理。Checkpoints如何将 checkpoint 转换为 HuggingFace safetensors 格式如需将训练产出的 checkpoint 转换为 HuggingFace safetensors 格式请使用verl/model_merger。该模块是 verl 官方的模型合并工具入口为verl/model_merger/__main__.py其核心组件包括verl/model_merger/fsdp_model_merger.py合并 FSDP 分片权重verl/model_merger/megatron_model_merger.py合并 Megatron 分片权重verl/model_merger/output_validation.py对合并后的输出进行校验verl/model_merger/base_model_merger.py合并的基类与公共逻辑。用法大致为通过python -m verl.model_merger配合相关参数指定模型类型、输入 checkpoint 路径与输出路径合并结果即为标准 HuggingFace 格式可直接加载到 transformers。Tritoncompile_module_from_src错误如果遇到类似下面的 Triton 编译错误堆栈请根据 配置文档 中的说明将use_torch_compile设置为False以禁用 fused kernel 的即时编译File .../site-packages/triton/runtime/jit.py, line 345, in lambda return lambda *args, **kwargs: self.run(gridgrid, warmupFalse, *args, **kwargs) File .../site-packages/triton/runtime/autotuner.py, line 338, in run return self.fn.run(*args, **kwargs) File .../site-packages/triton/runtime/jit.py, line 607, in run device driver.active.get_current_device() File .../site-packages/triton/runtime/driver.py, line 23, in __getattr__ self._initialize_obj() File .../site-packages/triton/runtime/driver.py, line 20, in _initialize_obj self._obj self._init_fn() File .../site-packages/triton/runtime/driver.py, line 9, in _create_driver return actives[0]() File .../site-packages/triton/backends/nvidia/driver.py, line 371, in __init__ self.utils CudaUtils() # TODO: make static File .../site-packages/triton/backends/nvidia/driver.py, line 80, in __init__ mod compile_module_from_src(Path(os.path.join(dirname, driver.c)).read_text(), cuda_utils) File .../site-packages/triton/backends/nvidia/driver.py, line 57, in compile_module_from_src so _build(name, src_path, tmpdir, library_dirs(), include_dir, libraries) File .../site-packages/triton/runtime/build.py, line 48, in _build ret subprocess.check_call(cc_cmd) File .../subprocess.py, line 369, in check_call raise CalledProcessError(retcode, cmd)从源码看该参数的作用use_torch_compile定义于 verl/workers/config/actor.py默认值为Trueuse_torch_compile: bool True。该参数同时存在于ref、engine相关配置如 verl/trainer/config/engine/fsdp.yaml以及 FSDP/VeOmni/AutoModel/Torchtitan 各后端的transformer_impl.py实现中用于决定是否对 fused kernel 启用torch.compile的 JIT 优化。当环境中 Triton 编译器无法正常编译如缺少 CUDA 头文件、编译器版本不匹配、或驱动 API 初始化失败时将其关闭即可绕过该错误路径actor_rollout_ref.actor.use_torch_compileFalse actor_rollout_ref.ref.use_torch_compileFalse注意关闭 JIT 后训练速度可能略有下降但功能不受影响可作为临时或长期稳定性方案。train batch size、mini batch size、micro batch size 的含义这三个 batch size 是 verl/PPO 类算法中最核心、也最容易混淆的配置。它们之间的关系如下原文档附有示意图核心逻辑与verl/workers/config/actor.py、verl/workers/config/critic.py中的校验逻辑一致train batch sizedata.train_batch_size一次 RL 训练迭代iteration采样的样本总数即 rollout 阶段生成并进入一次参数更新的经验量。其默认值为 1024见docs/examples/config.rst中的示例配置。mini batch sizeactor_rollout_ref.actor.ppo_mini_batch_sizePPO 每次梯度更新所用的子批量大小train_batch_size会被切分成若干个 mini batch 依次更新。actor.py中默认值为256并存在硬性校验train_batch_size ppo_mini_batch_size且train_batch_size必须能被ppo_mini_batch_size整除。micro batch sizeactor_rollout_ref.actor.ppo_micro_batch_size_per_gpu每个 GPU 上实际执行的微批量大小用于控制单卡显存占用。ppo_mini_batch_size必须能被 micro batch size 整除actor.py同时规定ppo_micro_batch_size全局写法与ppo_micro_batch_size_per_gpu每卡写法不能同时设置两者互斥且必须二选一在未启用use_dynamic_bsz时。总结三层关系train_batch_size决定一次迭代的总经验量ppo_mini_batch_size决定一次参数更新的样本量ppo_micro_batch_size_per_gpu决定单卡单次前向/反向的样本量三者逐层整除约束从大到小。Critic 侧critic.ppo_micro_batch_size_per_gpu、critic.ppo_mini_batch_size同理默认critic.ppo_mini_batch_size: 1。如何生成 Ray Timeline 分析训练性能Ray 自带性能追踪能力。在 verl 中只需在配置中设置ray_init.timeline_json_file指向一个 json 文件路径ray_init.timeline_json_file/tmp/ray_timeline.json训练结束时该文件会生成在指定路径。从源码看verl/trainer/main_ppo.py 中会读取config.ray_kwargs.get(timeline_json_file, None)若非空则调用ray.timeline(filename...)写入时间线verl/trainer/config/ppo_trainer.yaml中该字段默认值为null。生成后可使用chrome://tracing或 Perfetto UI 打开并查看 Ray Timeline直观分析各 task如 rollout、actor 更新、数据转移的时间线分布定位瓶颈。该文件展示了单节点 4 卡训练作业的完整 Ray 调度时间线是排查跨 task 串并行开销的利器。如何只为 wandb 设置代理如果访问 wandb 需要代理但又不想影响其他 HTTP 请求例如 ChatCompletionScheduler 与推理引擎的通信可以在训练作业脚本中追加如下配置而不要使用全局https_proxy环境变量trainer.wandb_proxyhttp://your proxy and port从源码看实现该参数在 verl/utils/tracking.py 中被消费——初始化 wandb 时如果config[trainer].get(wandb_proxy)存在则通过wandb.Settings(https_proxyconfig[trainer][wandb_proxy])将代理仅注入 wandb 客户端从而隔离代理范围不影响训练框架内其他模块的网络请求。推理与训练序列不匹配actor/grad_norm 持续升高症状与定位如果训练过程中actor/grad_norm指标持续增大很可能是推理引擎rollout与训练actor之间存在显著的精度不匹配。可用如下参数开启序列概率差异校验actor_rollout_ref.rollout.calculate_log_probsTrue开启后训练日志中会新增training/rollout_probs_diff_mean等指标用于量化推理引擎计算出的 log prob 与训练侧前向计算的差异。判定标准正常情况下training/rollout_probs_diff_mean应低于0.005如果观测值高于0.01说明推理引擎存在精度问题会持续污染 PPO 的优势估计导致 grad_norm 异常攀升。已知触发条件该精度问题在同时满足以下三个条件时已知会发生使用非 Hopper 架构的 GPU例如 A100、L20、B200 等使用存在相关 bug 的 vLLM 版本作为推理引擎对应 vLLM issue 22103输入输出文本较长例如多轮场景下使用 Qwen3 这类推理模型做 RL 训练。解决方案当上述三个条件同时满足且rollout_probs_diff_mean过高时推荐追加如下参数关闭级联注意力actor_rollout_ref.rollout.engine_kwargs.vllm.disable_cascade_attnTrue根因说明该问题的根源是 vLLM 所用 flash attention 的一个 bugFA2 kv-split 场景下的 LSE 输出错误。虽然上游 flash-attention 已提交修复见 flash-attention 的 “Fix LSE output error in FA2 kv-split” PR但截至文档维护时FAQ 最后更新于 2025-09-24该修复尚未随 vLLM 最新版本v0.10.2发布。因此在 vLLM 发布包含修复的新版本之前建议使用上述配置禁用 cascade attention 作为 workaround。其他相关排查类似的精度类问题还可能与 rollout 端的gpu_memory_utilization、tensor_model_parallel_size等配置相关参考 examples/tutorial/slurm/ray_on_slurm.slurm 中的设置。若开启calculate_log_probs后差异仍无法解释建议同时核对推理引擎与训练侧使用的模型权重、dtype如 bf16/fp16及序列长度配置是否一致。总结本文覆盖了 verl 社区最常遇到的九类问题从 Ray 断点调试与 raylet 注册失败、多节点/SLURM 集群部署到 arm64 平台 tensordict 安装、vLLM 非法内存访问、checkpoint 转 safetensors、Triton JIT 编译失败、batch size 层级关系、Ray Timeline 生成、wandb 专用代理再到推理-训练精度不匹配的定位与修复。每个解决方案都可在当前仓库找到对应的配置字段与源码实现如 verl/trainer/config/ppo_trainer.yaml、verl/workers/config/actor.py、verl/utils/tracking.py、examples/tutorial/slurm/ray_on_slurm.slurm。建议读者在实际训练前先核对本文涉及的配置项并在遇到问题时按“定位指标 → 确认条件 → 应用 workaround → 回归验证”的路径处理。更完整的配置字段说明可进一步阅读 配置详解文档 与 GSM8K 端到端示例。【免费下载链接】verlverl/HybridFlow: A Flexible and Efficient RL Post-Training Framework项目地址: https://gitcode.com/GitHub_Trending/ve/verl创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考