IsoExec: 切换 SkyRL 中的训练器-推理不匹配
vLLM 推出了 IsoExec,一种跨框架的统一执行抽象,旨在消除强化学习 (RL) 工作负载中训练引擎与推理引擎之间的数值不匹配。通过强制执行严格的执行合约并利用并行不变性内核 (parallelism-invariant kernels),IsoExec 确保了 rollout 引擎和训练器在位一致性 (bitwise consistency) 方面评估相同的策略,从而在仅增加 25% 性能开销的情况下,将平均端到端 rollout 与训练的 logprob 差异降低到 $10^{-7}$ 以下。
问题:训练器-推理不匹配
在 on-policy RL 中,系统必须执行两次相同的策略:一次在 rollout 引擎中采样 token,一次在训练器中重新计算 log 概率。在实践中,这两个阶段通常使用不同的引擎(例如,用于 rollout 的 vLLM 和用于训练的 Megatron),它们采用不同的内核、batch 形状和并行布局。
由于浮点数算术是非结合律的,这些系统性差异会导致不同的规约 (reduction) 顺序,即使在模型参数完全相同的情况下,也会改变 token 概率。这种不匹配可能会使 REINFORCE 和 GRPO 等 RL 算法不稳定,并导致奖励崩溃 (reward collapse)。例如,Fireworks 报告的一项 GLM-5.2 运行结果显示,其训练-推理 KL 散度约为 0.013,导致 45% 的 token 被通过 clipping 丢弃,随后在第 20 步左右发生奖励崩溃。
IsoExec 统一执行合约
IsoExec 通过使用 执行合约 (execution contract) 来解决这些差异,该合约声明了两个运行时必须遵循的每一个与位相关的执行选择。
合约结构与强制执行
- Cases and Regions (情况与区域): 合约将前向算子划分为“区域” (region,即由一个内核实现的算术跨度)。然后定义“情况” (case,例如
engine_prefill与trainer_fwd) 来指定如何处理每个区域。 - Composition (组合): 对于每一对 region-case,合约会选择一个特定的实现并将其固定为常量,例如累积数据类型 (accumulation dtypes) 和规约分解参数 (reduction-decomposition parameters,例如 split-K 分区计数)。
- Claims (声明): 这些是运行时强制执行的条件,例如拓扑声明 (topology claims),列出了规约树 (reduction tree) 被证明在位一致性方面是不变的,从而实现并行规模的特定并行规模。
- Identities (标识): 使用 SHA-256 摘要 (
semantic,numerical_policy, 和deployment) 来验证训练器和 rollout 引擎正在执行相同的经过验证的数值策略。
每个运行时的 contract adapter 会将这些规范绑定到框架的扩展点,并监控运行时以确保合规。
统一模型与并行不变性内核
IsoExec 实现了一种统一的模型定义,这种定义在各种分布式策略(包括 tensor、expert 和 sequence parallelism)中保持位一致性。
实现并行不变性
为了在不同的 GPU 布局下保持数值一致性,IsoExec 采用了固定的二进制规约树方法:
- Tensor Parallelism (TP): 使用
pik实现,IsoExec 将 K 维度划分为连续的叶子节点。每个叶子节点使用确定性的 Tensor Core MMA 与 FP32 累积,并且合约固定了 rank-to-leaf 映射和算术调度。 - Expert Parallelism (EP): Expert 输出按固定的路由顺序而非 rank 顺序进行组合。
- Sequence Parallelism (SP): IsoExec 复用与非-SP 系统相同的规约树,每个 rank 保留其自身的输出切片,从而确保无论是否启用 SP,训练器 logits 始终保持一致。
Chunkwise-Parallel Recurrent (CPR) Gated DeltaNet
线性注意力架构(如 Gated DeltaNet (GDN))通常在训练/prefill 阶段使用 chunkwise-parallel 形式,而在 decode 阶段使用 recurrent 形式,这会产生数值不匹配。以往通过在所有地方使用 recurrent 形式来修复此问题的尝试,导致了显著的慢速化(在某些工作负载上高达 5 倍)。
IsoExec 引入了 Chunkwise-Parallel Recurrent (CPR),它将循环 (recurrence) 作为主要功能,但通过在 chunk 之间进行并行化处理。对于 decode 阶段,它每 $C$ 个 token 这样进行重新同步隐藏状态 (hidden state),其中 $C$ 是 chunk 大度。这在保持高吞吐量的同时实现了位一致性:
| Stage | Native Mixed | Chunkwise Everywhere | Recurrent Everywhere | CPR |
|---|---|---|---|---|
| Bitwise Exact | No | Yes | Yes | Yes |
| Trainer Fwd+Bwd | 5.177 ms | 5.177 ms (1.00x) | 22.863 ms (4.42x) | 7.386 ms (1.43x) |
| Rollout Prefill | 0.844 ms | 0.844 ms (1.00x) | 3.679 ms (4.31x) | 1.412 ms (1.67x) |
| Rollout Decode | 0.0612 ms | 2.2374 ms (36.6x) | 0.0612 ms (1.00x) | 0.0846 ms (1.38x) |
实验结果
IsoExec 在单个 8xH100 节点上使用同步 RL 训练 Qwen3.5-35B-A3B 在 DAPO-Math-17k 上进行了测试。
数值准确性
在 50 个 step 步数内,平均 pre-update rollout 与训练的绝对 logprob 差异从 $10^{-3}$ (native SkyRL) 降低到了 $10^{-7}$ 以下 (IsoExec)。每个 step 的平均最大差异从 5.073 降至 $10^{-4}$。
性能开销销
消除不匹配引入了与 native SkyRL 栈相比的性能惩罚:
| Metric | Native | IsoExec | Overhead |
|---|---|---|---|
| Generation | 591.3 s | 776.6 s | 31.3% |
| Policy Training | 498.6 s | --- | 18.6% |
| Full RL Step | 1224.6 s | 1534.0 s | 25.3% |
虽然实现了数值一致性,但团队在短期的 59 步测试窗口内并未观察到显著的奖励 (reward) 奖励提升。
Sources
相关
- Dispatch
- Dispatch
- 项目
- Dispatch
- Dispatch