slime 训练故障排查实战:13 个高频 FAQ 的根因分析与解决方案
【免费下载链接】slimeslime is an LLM post-training framework for RL Scaling.项目地址: https://gitcode.com/GitHub_Trending/slime12/slime
本文围绕 slime(LLM 后训练 / RL Scaling 框架)在真实训练过程中最常遇到的 13 类问题,逐一给出根因分析、排查思路与可落地的参数级解决方案。问题覆盖 checkpoint 加载乱码、Ray 任务卡死、OOM、依赖库冲突、续训、batch size 语义、data packing、SGLang 服务异常、梯度爆炸与 NaN/Inf 等场景。读完本文,你将能够根据报错特征快速定位故障源头,并准确使用--load、--max-tokens-per-gpu、--colocate、--rollout-stop等关键参数完成修复。
1. 训练出现乱码:Megatron 没有正确加载 checkpoint
现象:训练日志/输出中出现乱码文本,通常意味着 Megatron 加载的权重并不是你期望的模型权重。
根因:Megatron 没有按预期加载 checkpoint。请检查--load与--ref-load参数指定的目录下是否存在对应的 ckpt。注意一个关键约束:Megatron 只能加载包含latest_checkpointed_iteration.txt文件的目录。这一点在源码中有直接体现,slime/backends/megatron_utils/checkpoint.py 判断 checkpoint 目录是否有效时,正是检查latest_checkpointed_iteration.txt文件是否存在。
解决:确认--load/--ref-load指向了由 Megatron 正确落盘的 checkpoint 目录;如果需要加载特定的迭代步数,可通过--ckpt-step指定步数。源码中--ckpt-step的消费逻辑位于 slime/backends/megatron_utils/model.py:当指定了ckpt_step时,会以该步数作为恢复迭代点;而 slime/backends/megatron_utils/actor.py 会针对 ref/teacher 等不同模型 tag 分别使用--ref-ckpt-step、--opd-teacher-ckpt-step覆盖该值。
2. 任务一直卡在 Ray 提交页面:GPU 资源与拓扑不匹配
现象:任务提交到 Ray 后长时间停在提交/调度页面,不进入实际训练。
根因:任务所需的 GPU 数量与当前集群可分配 GPU 数量不匹配。请先确认当前任务是训推一体(co-located)还是训推分离(decoupled),然后按下列规则核对:
- 训推一体:训练与推理共用 GPU。检查是否设置了
--colocate参数开启训推一体模式;并确认当前任务总卡数 ≥actor_num_nodes * actor_num_gpus_per_node。 - 训推分离:训练与推理各用各的 GPU。确认当前任务总卡数 ≥
actor_num_nodes * actor_num_gpus_per_node + rollout_num_gpus。
从源码看,actor 的总卡数正是由这两个参数决定的:slime/backends/megatron_utils/arguments.py 中args.world_size = args.actor_num_nodes * args.actor_num_gpus_per_node;而--colocate的开启会显著改变权重同步路径(例如 slime/backends/megatron_utils/update_weight/init.py 中--update-weight-mode=delta与--colocate互斥,以及 update_weight/update_weight_from_tensor.py 依据 actor GPU 范围判定 colocated engine 数量),因此这两种模式下可用的推理引擎数量与所需总卡数是完全不同的。
3. 训着训着 OOM:max_tokens_per_gpu到底有什么用
现象:训练中途报显存不足(OOM)。
根因:OOM 往往是因为--max-tokens-per-gpu设置过高。该参数的含义是:训练过程中每张 GPU 上最多可以放多少个 token。需要注意,--max-tokens-per-gpu只有在开启--use-dynamic-batch-size的情况下才会生效——这一点在 slime/utils/arguments.py 的参数说明中写得很清楚,并且校验逻辑位于 slime/utils/arguments.py:当开启动态 batch size 而max_tokens_per_gpu未设置时,会直接断言报错。
解决:
- 如果担心 OOM,可先把该值设为
rollout_max_response_len / cp_size,之后再为了提升训练效率逐步增大。 - 从底层调度看,
max_tokens_per_gpu与上下文并行(CP)强耦合:slime/utils/arguments.py 明确指出开启 CP 时该值应约为max_response_len // cp_size而非max_response_len;slime/utils/dp_schedule.py 的调度不变量也规定:除单个样本超长而独占一个 micro-batch 的特殊情况外,每个 mbs 的 token 数必须<= max_tokens_per_gpu * cp_size。 - 如果
max_tokens_per_gpu已经很小仍然 OOM,请检查是否单次生成的数据过长,此时需要开启上下文并行--context-parallel-size;如果使用了自定义数据生成流程,请确认多轮生成场景下总长度是否远超预期。
4. 多机训练时 transformers 库找不到模型:本地文件写冲突
现象:多机训练时,transformers报出找不到某个模型的错误。
根因:多个进程同时通过AutoConfig.from_pretrained或AutoModelForCausalLM.from_pretrained的方式读取本地模型文件,出现了文件系统的读写冲突。
解决:设置--model-name参数可以缓解这一问题。该参数定义在 slime/utils/arguments.py 附近,其作用是为模型相关操作提供显式命名,减少多进程对本地缓存/文件位置的隐式推断竞争。
5. 如何续训(resume)
slime 的续训操作非常简单:直接将--load设置为--save的目录即可。前提是--save目录中包含 Megatron 可识别的 checkpoint(见第 1 节:目录内需存在latest_checkpointed_iteration.txt)。若需从特定步数续训,结合--ckpt-step使用即可。
6. batch size 是如何计算的
batch size 的语义在 RL 训练中容易混淆,slime 的规则如下:
- 一个 rollout 会使用
rollout_batch_size条 prompt; - 每条 prompt 会采样
n_samples_per_prompt条; - 因此一个 rollout 共产生
rollout_batch_size * n_samples_per_prompt条数据。
在此基础上,--num-steps-per-rollout决定每个 rollout 训练几步,这相当于把global_batch_size设置为rollout_batch_size * n_samples_per_prompt // num_steps_per_rollout。这一点在参数定义中有一致说明:slime/utils/arguments.py 特别提醒 "the gbs is of sample, not of prompts",即如果想每个 rollout 只训练一步,global_batch_size应设为rollout_batch_size * n_samples_per_prompt。同时 slime/backends/megatron_utils/model.py 也据此推导总训练步数:train_iters = num_rollout * rollout_batch_size * n_samples_per_prompt // global_batch_size。
7. slime 是否进行 data packing / varlen 处理
是的,默认进行。data packing 指在训练过程中将长短不一的样本拼接在一起,从而提升 GPU 利用率。slime 默认开启这一行为,并且在 Megatron 参数校验阶段被强制设定:slime/backends/megatron_utils/arguments.py 中validate_args直接执行args.variable_seq_lengths = True,注释为 "always use varlen"。同时它还对 MoE 场景做了兼容处理:当moe_token_dispatcher_type为allgather时(其不支持变长序列),会强制切换为alltoalldispatcher。
在动态 batch 路径下,packing 还配合max_tokens_per_gpu与 FLOPs 均衡策略工作:参见 slime/utils/arguments.py 中的--balance-data(用 Karmarkar-Karp 算法按预估 FLOPs 均衡 DP rank 间的训练负载)与--balance-by-flops(基于 FLOPs 而非 first-fit 的 token 打包),以及底层实现 slime/utils/dp_schedule.py 与 slime/utils/seqlen_balancing.py。
8. sglang 报Max retries exceeded with url: /get_model_info (Caused by NewConnectionError)
根因:该问题主要源于单机内运行了多个 sglang server 导致端口冲突。目前 slime 团队仍在与 sglang 团队合作解决此问题。
临时缓解方案:尽可能减少单机内 sglang server 的数量,例如将 tensor parallelism 设为tp=8,以降低同一节点上的引擎实例数。
9. grad norm 很高、训练崩溃:先检查数据与模型是否匹配
排查顺序:
- 首先确保数据与模型是匹配的。例如,如果数据已经预先做了 chat template,请核对这个 template 是否与原始模型一致——模板不匹配是导致梯度异常居高不下的常见原因。
- 如果数据确认无误,请参考 slime 的 Debug 指南(中文版见 docs/zh/developer_guide/debug.md)进行更深入的分析,其中包含日志、profiling 与 trace 等排查手段(相关工具见 tools/analyze_profile.py、tools/trace_timeline_viewer.py)。
10. sglang 生成极慢、GPU 功率打满且长时间无输出:stop token 配置缺失
现象:sglang 生成耗时极长,GPU 功率满载,但长时间没有输出。
根因:--hf-checkpoint对应的模型没有正确配置 stop token,导致生成过程无法在期望位置及时终止。
解决:通过--rollout-stop或--rollout-stop-token-ids显式设置终止条件:
--rollout-stop:接收一个或多个字符串作为停止词(定义于 slime/utils/arguments.py);--rollout-stop-token-ids:接收一个或多个整数 token id(定义于 slime/utils/arguments.py)。当命令行难以直接传入特殊 token 时(如<eos>等),使用 token id 更稳妥。
这两个参数最终会透传给 sglang 引擎的stop/stop_token_ids字段:slime/rollout/sglang_rollout.py;同时数据集配置中也可以按需覆盖它们(slime/rollout/sglang_rollout.py)。
11. sglang 报an illegal memory access was encountered
根因:根据 SGLang 官方文档的说明,这很可能是OOM(显存不足)导致的非法内存访问。
解决:考虑缩小--sglang-mem-fraction-static,即降低 sglang 静态显存占用比例,为 KV cache 之外的显存需求留出余量。
12. torch compile / inductor 的JSONDecodeError
现象:训练过程中出现与 torch compile/inductor 相关的JSONDecodeError。
根因:一般是 torch compiler 在读写编译缓存(cache)时出现问题,常见于多进程并发访问同一缓存目录的场景。
解决:在 Ray 配置的env_vars中加入环境变量,强制禁用缓存读写:
env_vars: {"TORCHINDUCTOR_FORCE_DISABLE_CACHES": "1"}13. 训练中出现 grad NaN 或 Inf
现象:梯度变为 NaN 或 Inf,训练无法继续。
排查与解决:在确认数据与模型兼容、学习率设置合理之后,可以通过设置--no-check-for-nan-in-loss-and-grad跳过对应的 NaN/Inf 检查训练步,作为临时规避手段继续观察训练行为。但请注意:该参数只是跳过检查步骤,并未修复数值不稳定的根源,建议配合第 9 节的 Debug 指南定位真正原因。
小结:故障排查速查表
| 问题 | 首选排查点 | 关键参数/手段 |
|---|---|---|
| 训练乱码 | checkpoint 目录完整性 | --load/--ref-load、--ckpt-step、latest_checkpointed_iteration.txt |
| 卡在 Ray 提交页 | 卡数是否足够、拓扑模式 | --colocate、actor_num_nodes * actor_num_gpus_per_node、rollout_num_gpus |
| 训练 OOM | 单卡 token 上限 | --max-tokens-per-gpu、--use-dynamic-batch-size、--context-parallel-size |
| transformers 找不到模型 | 多进程文件写冲突 | --model-name |
| 续训 | load/save 目录 | --load=<save 目录> |
| batch size 语义 | rollout 与训练步的换算 | rollout_batch_size * n_samples_per_prompt // num_steps_per_rollout |
| 数据打包 | 默认开启 | varlen(variable_seq_lengths=True)、--balance-data、--balance-by-flops |
| sglang 连接失败 | 单机引擎过多/端口冲突 | 提高tp,减少单机 sglang server 数 |
| 梯度爆炸 | 数据与模板匹配性 | 参考 Debug 指南 |
| 生成慢且无输出 | stop token 缺失 | --rollout-stop、--rollout-stop-token-ids |
| sglang 非法内存访问 | 显存不足 | --sglang-mem-fraction-static |
| torch compile 报错 | 编译缓存读写 | TORCHINDUCTOR_FORCE_DISABLE_CACHES=1 |
| grad NaN/Inf | 数值不稳定 | --no-check-for-nan-in-loss-and-grad |
所有参数的完整定义与取值范围说明均可追溯至 slime/utils/arguments.py 与 slime/backends/megatron_utils/arguments.py,在调整参数前建议先阅读对应 help 文本,并结合实际训练日志逐步验证。
【免费下载链接】slimeslime is an LLM post-training framework for RL Scaling.项目地址: https://gitcode.com/GitHub_Trending/slime12/slime
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考