slime框架训推一致性预处理与数据采集
1. 简介
slime 框架采用"训练侧 Megatron + 推理侧 SGLang"的训推分离架构。
在定位精度差异时,由于训练侧 old_log_prob 默认输入为 prompt + response,而推理侧 prefill 输入仅为 prompt,导致两侧输入 token 不一致,无法直接比对 dump 出的统计量。
本文档专门针对训推一致性精度定位场景,提供完整的预处理与数据采集流程:
通过预处理统一两侧 prefill 阶段的输入 token,确保数据满足并行切分、batch 及 padding 等工程约束。参见训推一致性预处理。
仅采集训练侧
old_log_prob与推理侧 prefill 对应阶段的数据,用于逐 rank 比对以快速定位精度差异来源。参见训推两侧 msProbe 数据采集。
对于不要求训推输入对齐的场景,可使用 slime 框架通用的采集方式,详细介绍请参见《slime 框架训推精度数据采集》。
2. 环境准备
安装 msProbe 工具,详情请参见《msProbe 工具安装指南》。
pip install mindstudio-probe
运行环境与镜像:
Dockerfile构建镜像:可基于 Slime_ascend Dockerfile 构建镜像和环境。
3. 训推一致性预处理
训推一致性比对前,须保证训练和推理时的输入 token 与序列长度一致,并满足并行切分、batch 配置等约束,才能确保 dump 的精度数据可匹配比对。
预处理目标(两侧分别要达到的效果)如下:
目标侧 |
目标效果 |
对应小节 |
|---|---|---|
推理侧 |
SGLang 第一次 EXTEND(prefill)输入为 prompt token;关闭图模式,并满足 DP / chunked prefill、并行切分、序列长度对齐等约束,保证采集到正式 prefill 前向 |
|
训练侧 |
Megatron |
3.1 prompt-only 输入对齐
预处理动作:将训练侧 old_log_prob 的输入从「prompt + response」截断为仅含 prompt,使其与推理侧 prefill 输入一致。
原因:slime 正常 GRPO 链路中,rollout 产出 sample.tokens(prompt + response),训练侧 old_log_prob 默认对完整序列计算 log prob。训推一致性场景只需比对 prefill 段,因此训练侧须去掉 response,仅保留 prompt token。
代码实现方式:见 4.2 训练阶段数据采集:新增 consistent_dump_utils.py,在 DUMP_ON=1 且 PROMPTS_ONLY=1 时,于 train_actor 入口对 rollout batch 做 prompt-only 副本后再执行 compute_log_prob,并在采集完成后跳过 actor 训练。
3.2 序列长度与 padding 约束
为了保证训练和推理时使用的模型权重完全一致,并消除因 padding 策略不同导致的浮点精度差异,训练侧和推理侧必须使用相同的序列长度对齐策略。
建议将训练侧的填充系数 --data-pad-size-multiplier 设置为 1,确保序列长度仅对齐到张量并行度(TP)的倍数,从而最小化 Padding Token 的数量和潜在的数值误差。
训练侧 Megatron 配置
训练侧 Megatron 在 get_batch 阶段,会根据以下公式计算每个序列需要填充到的目标长度:
pad_size = tensor_model_parallel_world_size * data_pad_size_multiplier
tensor_model_parallel_world_size(TP):张量并行度。例如使用 4 张卡做张量并行训练,则 TP=4。TP 通常配置为 2 的幂次方,具体值取决于卡的数量。
data_pad_size_multiplier(multiplier):填充步长的系数。保证所有输入序列的长度是
TP × multiplier的整数倍。multiplier 默认值为 128,建议配置为 1。
推理侧(SGLang)数据预处理要求
SGLang 本身支持任意长度的动态输入,但为了与 Megatron 训练侧对齐,必须在将数据传入 SGLang 之前,在预处理阶段按与训练侧相同的 pad_size 完成序列长度对齐。
具体操作取决于训练侧的配置:
配置 |
pad_size |
说明 |
|---|---|---|
推荐 TP=1,multiplier=1 |
1 |
无需填充。直接使用原始 prompt 长度即可,训练侧与推理侧天然对齐。 |
TP>1,multiplier=1 |
TP |
必须填充。将 prompt 长度补齐到 TP 的整数倍。 |
TP>1,multiplier=128 |
TP × 128 |
必须填充。将 prompt 长度补齐到 |
dump 模式须设置 --data-pad-size-multiplier 1;若训练 TP>1,须保证传入两侧的 prompt 长度均为 TP × multiplier 的整数倍。
3.3 SGLang DP 与 chunked prefill 约束
启用 --sglang-dp-size > 1 时,须满足:
sglang-chunked-prefill-size / sglang-dp-size > 实际 prefill prompt 长度
3.4 训推并行切分一致
训推一致性比对要求训练与推理的模型并行切分方式一致,确保两侧各 rank 承担相同的参数分片与计算路径,dump 数据才能按 rank 一一对应。
维度 |
训练侧(Megatron) |
推理侧(SGLang) |
对齐要求 |
|---|---|---|---|
TP |
|
|
两侧 TP 须一致 |
PP |
|
通常为 1 |
两侧 PP 须一致 |
CP |
|
通常为 1 |
两侧 CP 须一致 |
DP |
由 world_size 与 TP/PP/CP 推导 |
|
两侧 DP 语义须一致 |
3.5 单条 prompt 输入与 DP 配置
为保证训推两侧处理同一条 prompt,且训练侧 Megatron 能按 DP 正常分发样本,dump 模式须固定:
--rollout-batch-size 1 # 每轮 rollout 仅 1 条 prompt
--n-samples-per-prompt ${DP} # 须等于 DP,保证训练正式运行
--global-batch-size ${DP} # rollout-batch-size × n-samples-per-prompt
数据并行度计算公式:
DP = world_size / TP / PP / CP
其中 world_size 为训练参与进程总数(通常等于训练 NPU 卡数),TP、PP、CP 分别对应 tensor / pipeline / context 并行度。
示例(4 卡训练,TP=1, PP=1, CP=1):
DP = 4 / 1 / 1 / 1 = 4
→ --rollout-batch-size 1 --n-samples-per-prompt 4 --global-batch-size 4
若 global_batch_size 无法被 DP 整除,Megatron 训练会报错。
3.6 禁用数据均衡与动态 batch
训推一致性场景须关闭会改变 batch 切分或样本分布的优化项,避免训练侧各 rank 拿到的数据与推理 prefill 不对齐:
参数 |
要求 |
原因 |
|---|---|---|
|
禁用(不传) |
自动均衡会重排 batch,破坏 rank 与样本的一一对应 |
|
禁用(不传) |
动态 batch 会改变 micro-batch 切分,影响 dump 可比对性 |
dump 模式下同时建议关闭 --rollout-shuffle、--over-sampling-batch-size 等会引入随机采样的参数,保证每轮输入确定可复现。
3.7 关闭 CUDA Graph 图模式
训推一致性 dump 须关闭 SGLang 的 CUDA Graph(昇腾场景下为图编译缓存)优化,否则 msProbe 无法正确钩住每次 EXTEND 前向的算子,dump 数据不完整或与 eager 模式不一致。
slime 启动 SGLang 时须指定:
--sglang-disable-cuda-graph
4. 训推两侧 msProbe 数据采集
完成第 3 章预处理约束后,按本节分别配置并采集推理侧(generate / prefill)与训练侧(old_log_prob)的 msProbe 数据。
4.1 创建配置文件
训推两侧各需一份 config.json。采集统计量时 task 配置为 statistics,示例如下:
推理侧(config_generate.json):
{
"task": "statistics",
"dump_path": "/example_dump_path/msprobe_dump/generate",
"rank": [],
"step": [0],
"level": "mix",
"async_dump": false,
"extra_info": true,
"statistics": {
"scope": [],
"list": [],
"tensor_list": [],
"data_mode": ["all"],
"summary_mode": "statistics"
}
}
训练侧(config_actor.json):
{
"task": "statistics",
"dump_path": "/example_dump_path/msprobe_dump",
"rank": [],
"step": [0],
"level": "mix",
"async_dump": false,
"extra_info": true,
"statistics": {
"scope": [],
"list": [],
"tensor_list": [],
"data_mode": ["all"],
"summary_mode": "statistics"
}
}
主要参数说明:
task:
statistics表示采集统计量;若需真实张量,配置为tensor。dump_path:dump 保存根路径;训练侧代码会在
dump_path下动态拼接old_log_prob子目录落盘,推理侧直接指向generate子目录落盘。step:采集步数,训推一致性 dump 通常仅采
step0。level:
mix表示同时采集 Module 级和 API 级数据。
以上配置参数的详细介绍请参见《配置文件介绍》。
4.2 训练阶段数据采集
训练阶段精度数据采集在 slime 的 Megatron 训练后端完成。在 slime/backends/megatron_utils/actor.py 中实例化 PrecisionDebugger,在 old_log_prob 前向前后调用 start、stop 接口,并在 stop 之后调用 step() 推进步数。PrecisionDebugger 接口更多介绍请参见《PyTorch 场景精度数据采集》。
以下展示训推一致性 dump 的代码修改方式(以 slime v0.2.2 为例)。修改步骤如下。
新增
slime/backends/megatron_utils/consistent_dump_utils.py"""Utilities for train-inference consistency msProbe dump.""" from copy import deepcopy import torch from slime.utils.types import RolloutBatch def copy_rollout_data_prompts_only(rollout_data: RolloutBatch) -> RolloutBatch: """Return a copy with tokens truncated to prompt-only (no response).""" dump_data = deepcopy(rollout_data) new_tokens, new_total_lengths, new_response_lengths = [], [], [] for tokens, total_length, response_length in zip( dump_data["tokens"], dump_data["total_lengths"], dump_data["response_lengths"], strict=True, ): prompt_length = total_length - response_length new_tokens.append(tokens[:prompt_length]) new_total_lengths.append(prompt_length) new_response_lengths.append(0) dump_data["tokens"] = new_tokens dump_data["total_lengths"] = new_total_lengths dump_data["response_lengths"] = new_response_lengths if "loss_masks" in dump_data: ref = dump_data["loss_masks"][0] if isinstance(ref, torch.Tensor): dump_data["loss_masks"] = [ torch.tensor([], dtype=ref.dtype, device=ref.device) for _ in new_tokens ] else: dump_data["loss_masks"] = [[] for _ in new_tokens] return dump_data
在
slime/backends/megatron_utils/actor.py的MegatronTrainRayActor.init中实例化 PrecisionDebugger须在
monkey_patch_torch_dist()之前实例化,避免与bias_swiglu_fusion冲突。class MegatronTrainRayActor(TrainRayActor): def init( self, args: Namespace, role: str, with_ref: bool = False, ) -> int | None: + # [msProbe] 训练侧精度采集开关 + dump_flag = int(os.environ.get("DUMP_ON", 0)) + if dump_flag: + from msprobe.pytorch import PrecisionDebugger, seed_all + seed_all(mode=True) + self.debugger = PrecisionDebugger(config_path=os.environ["MSPROBE_CONFIG_PATH"]) + self.dump_path_prefix = self.debugger.config.dump_path + else: + self.debugger = None monkey_patch_torch_dist() super().init(args, role, with_ref) ...
在
slime/backends/megatron_utils/actor.py的train_actor中采集 old_log_prob 并跳过 actor 训练def train_actor(self, rollout_id: int, rollout_data: RolloutBatch) -> None: + # [msProbe] 训推一致性 dump:仅采集 old_log_prob 前向(prompt-only),完成后跳过 actor 训练 + if int(os.environ.get("DUMP_ON", 0)): + from .consistent_dump_utils import copy_rollout_data_prompts_only + + dump_rollout_data = copy_rollout_data_prompts_only(rollout_data) + dump_data_iterator, dump_num_microbatches = get_data_iterator( + self.args, self.model, dump_rollout_data + ) + self._switch_model("old_actor" if self.args.keep_old_actor else "actor") + if self.debugger: + self.debugger.service.config.dump_path = os.path.join( + self.dump_path_prefix, "old_log_prob" + ) + self.debugger.start(model=self.model) + self.compute_log_prob( + dump_data_iterator, + dump_num_microbatches, + store_prefix="", + ) + if self.debugger: + self.debugger.stop() + self.debugger.step() + train_dump_utils.save_debug_train_data( + self.args, rollout_id=rollout_id, rollout_data=rollout_data + ) + return # Create data iterator for log_probs and train. data_iterator, num_microbatches = get_data_iterator(self.args, self.model, rollout_data) ...
说明:
训推一致性场景仅采集 old_log_prob 一个阶段;
debugger.step()在stop()之后调用一次即可。
4.3 推理阶段数据采集
slime 框架推理侧使用 SGLang 引擎执行 rollout 生成。
SGLang 从 0.5.11 版本起原生内置 msProbe 能力,因此低于 0.5.11 版本须按照本节操作进行侵入式修改,不低于 0.5.11 版本直接传配置参数。请根据 SGLang 版本选择操作方法:
SGLang 版本 |
操作方法 |
|---|---|
< 0.5.11 |
侵入式修改 |
≥ 0.5.11 |
已原生内置msProbe工具,可直接在 |
在 sglang/srt/model_executor/model_runner.py 中插入 PrecisionDebugger 接口。修改步骤如下。
在
ModelRunner.__init__末尾实例化 debuggerself.forward_pass_id = 0 self.draft_model_idx = draft_model_idx + # [msProbe] 推理侧精度采集,由 SGLANG_MSPROBE_DUMP=1 开启 + if int(os.environ.get("SGLANG_MSPROBE_DUMP", "0")): + from msprobe.pytorch import PrecisionDebugger, seed_all + seed_all(mode=True) + self.debugger = PrecisionDebugger(config_path=os.environ["MSPROBE_GENERATE_CONFIG"])
在
forward()中对真实 prefill 采集仅对 token 数 ≥
MSPROBE_MIN_DUMP_TOKENS的 EXTEND 前向 dump,跳过启动阶段约 1 个 token 的 dummy forward。def forward(self, forward_batch, ...): self.forward_pass_id += 1 + _msprobe_dump = False + if hasattr(self, "debugger"): + _min_tokens = int(os.environ.get("MSPROBE_MIN_DUMP_TOKENS", "2")) + _num_tokens = ( + forward_batch.input_ids.numel() + if forward_batch.input_ids is not None else 0 + ) + if forward_batch.forward_mode.is_extend(include_draft_extend_v2=True) \ + and _num_tokens >= _min_tokens: + _msprobe_dump = True + self.debugger.start(model=self.model, rank_id=self.gpu_id) ... output = ... + if hasattr(self, "debugger") and _msprobe_dump: + self.debugger.stop() + self.debugger.step() return output
5. 启动命令
训推一致性 dump 模式与正式训练隔离。启动前需先下发训练/推理侧环境变量,再按建议参数启动 slime。
5.1 环境变量配置
slime 基于 Ray 启动训练 Worker 与推理引擎,环境变量须通过 ray job submit 的 runtime-env-json 的 env_vars 下发,才能保证 Ray 子进程同样生效。
训练侧:
{
"env_vars": {
"DUMP_ON": "1",
"PROMPTS_ONLY": "1",
"TORCHDYNAMO_DISABLE": "1",
"MSPROBE_SEED": "1234",
"MSPROBE_CONFIG_PATH": "/path/to/config_actor.json"
}
}
变量 |
说明 |
|---|---|
|
训练侧 msProbe 总开关;0 或未设则与原始逻辑一致 |
|
训练仅跑 old_log_prob prompt 段并跳过 actor 训练 |
|
训练侧 config.json 路径 |
|
固定随机种子,保证多次运行结果可复现 |
|
遇 dynamo 报错时全局关闭 |
推理侧(SGLang 版本 < 0.5.11,需侵入式插桩时):
{
"env_vars": {
"SGLANG_MSPROBE_DUMP": "1",
"MSPROBE_GENERATE_CONFIG": "/path/to/config_generate.json",
"MSPROBE_MIN_DUMP_TOKENS": "2"
}
}
变量 |
说明 |
|---|---|
|
推理侧 msProbe 开关 |
|
推理侧 config.json 路径 |
|
过滤启动阶段约 1 个 token 的 dummy EXTEND forward,避免采集 warmup 探针请求(见下表) |
因 SGLang engine 初始化时会执行一次约 1 个 token 的 dummy EXTEND forward(用于 warmup / 图编译探测),MSPROBE_MIN_DUMP_TOKENS 用于过滤推理侧极短 EXTEND 前向:
前向类型 |
典型 token 数 |
|
|---|---|---|
启动 dummy forward |
约 1 |
跳过,不 dump |
正式 rollout prefill |
prompt 长度 |
采集,作为 generate |
5.2 启动参数建议
# rollout:仅 1 次;1 条 prompt,n-samples = DP
--num-rollout 1
--rollout-batch-size 1
--n-samples-per-prompt ${DP} # DP = world_size / TP / PP / CP
--global-batch-size ${DP}
# 训练并行(推荐 TP=1,无填充约束)
--tensor-model-parallel-size 1
--pipeline-model-parallel-size 1
--context-parallel-size 1
--data-pad-size-multiplier 1
--no-gradient-accumulation-fusion
# 勿传 --balance-data、--use-dynamic-batch-size
# SGLang(训推 TP/DP 与 §3.4 对齐;图模式见 §3.7)
--sglang-disable-cuda-graph
--sglang-chunked-prefill-size 16384 # 须满足 chunked_prefill_size/dp_size > prompt 长度
4 卡示例(TP=1, PP=1, CP=1 → DP=4):
--rollout-batch-size 1
--n-samples-per-prompt 4
--global-batch-size 4
--tensor-model-parallel-size 1
--rollout-num-gpus-per-engine 4 # 启用 DP-Attention 时该值为 DP 而非 TP,此处 DP=4、TP=1,与训练侧 TP=1 一致
--sglang-dp-size 4
--sglang-enable-dp-attention
dump 模式建议关闭 eval、不保存 checkpoint,并将日志写入实验目录 run.log。
6. dump 结果目录
训推一致性场景的 dump 落盘目录结构如下(以 dump_path 根目录 /example_dump_path/msprobe_dump 为例):
/example_dump_path/msprobe_dump/
├── generate/ # 推理 prefill 采集数据
│ └── step0/
│ └── rank{ID}/
│ ├── dump.json
│ ├── stack.json
│ └── construct.json
└── old_log_prob/ # 训练 old_log_prob 采集数据
└── step0/
└── rank{ID}/
├── dump.json
├── stack.json
└── construct.json
各级目录及文件说明:
rank{ID}:设备 ID,每张卡的数据保存在对应 rank 目录下。
dump.json:API 或 Module 前反向数据的统计量(Max/Min/Mean/L2 Norm 等)。详见《PyTorch 场景精度数据采集》。
stack.json:API/Module 的调用栈信息。
construct.json:分层分级结构信息。
rank 对齐说明:训推分离架构下,训练与推理运行在不同卡上,两侧 rank ID 通常无法一一对应(例如 4 卡场景:前 2 张卡跑推理、后 2 张卡跑训练,generate 侧 rank 目录可能从 rank2 起,与训练侧 rank0 不对齐)。因此可视化比对只能按单卡逐 rank 进行,须将路径指定到具体的 rank 目录,不能使用多卡批量比对。
7. msProbe 可视化比对
msprobe graph_visualize \
-tp /example_dump_path/msprobe_dump/generate/step0/rank0 \
-gp /example_dump_path/msprobe_dump/old_log_prob/step0/rank0 \
-o /example_dump_path/msprobe_vis
tensorboard --logdir /example_dump_path/msprobe_vis
比对时 -tp 指定推理(generate)数据,-gp 指定训练(actor)数据;须逐 rank 单卡比对,路径指定到对应 rank 目录。