执行摘要
- 一句话:移除失效 grad_offload 配置,属 Breaking 清理
- 推荐动作:值得快速阅读(约 15 分钟),重点关注两点:一是
verl/workers/config/engine.py 如何通过 dataclass + 生成配置联动维护配置契约,二是本 PR 与 #7536/#7466 形成的“清理死配置键”模式。如果有外部 Megatron 脚本或自定义配置,需要检查是否引用 grad_offload 并完成迁移。实现本身较机械,不需要深读。
功能与动机
PR body 明确指出:The option was assigned to MegatronEngine._is_offload_grad but never consumed. Gradient buffer lifecycle already follows param_offload through the engine context, so removing this option does not change runtime behavior. 动机是消除误导性配置键,避免用户误以为存在独立的梯度 offload 开关,同时让 param_offload 成为唯一管理参数/梯度驻留的入口,并提前搜索确认没有其他 open PR 处理 grad_offload。
实现拆解
变更入口是 verl/workers/config/engine.py 的 EngineConfig dataclass,随后逐层清理引用。
- 配置层清理:删除
EngineConfig.grad_offload: bool = False 字段及其注释,并在 McoreEngineConfig 文档字符串中把 param_offload 的语义扩展为“offload 参数到 CPU,并在引擎非活跃时释放梯度缓冲”。
- 引擎层收敛:在
verl/workers/engine/megatron/transformer_impl.py 的 MegatronEngine.__init__ 中删除 self._is_offload_grad = self.engine_config.grad_offload,初始化只保留 _is_offload_param 与 _is_offload_optimizer。
- 示例与测试覆盖删除:从 53 个文件中的 shell 脚本移除
grad_offload 相关环境变量与参数覆盖,涉及 tests/special_e2e/run_ppo_trainer_megatron.sh、run_v1_separate_async*.sh、tests/special_npu/nightly_ci_ascend/*.sh 以及 examples/ 下脚本;例如删除 COMMON_GRAD_OFFLOAD、ACTOR_GRAD_OFFLOAD、CRITIC_GRAD_OFFLOAD 变量及 actor_rollout_ref.actor.megatron.grad_offload=$... 等参数。
- 生成配置与文档同步:重新生成
verl/trainer/config/_generated_ppo_megatron_trainer.yaml 等扁平配置,修改 verl/trainer/config/engine/megatron.yaml 删除 grad_offload 键并更新 param_offload 注释,同时更新相关文档说明。
- 测试验证:更新
tests/workers/config/test_engine_config_on_cpu.py 的 parametrize 参数列表(移除 "grad_offload")与 tests/models/test_engine.py 的 kwargs;PR body 报告 CPU 配置测试 10 passed、shell 脚本 bash -n 通过、pre-commit 全部通过,且无需改动 CI workflow。
关键文件:
verl/workers/config/engine.py(模块 引擎配置;类别 source;类型 core-logic;符号 EngineConfig, McoreEngineConfig): 删除 EngineConfig.grad_offload 字段并更新 McoreEngineConfig 文档,是本次配置契约变更的源头。
verl/workers/engine/megatron/transformer_impl.py(模块 引擎实现;类别 source;类型 core-logic;符号 MegatronEngine.init): 移除 MegatronEngine.__init__ 中唯一的 _is_offload_grad 赋值,确认该标志在引擎层面从未被消费。
verl/trainer/config/engine/megatron.yaml(模块 训练配置;类别 config;类型 configuration): Megatron 引擎默认配置模板,删除 grad_offload 键并更新 param_offload 注释,是用户直接可见的配置入口。
tests/special_e2e/run_ppo_trainer_megatron.sh(模块 端到端测试;类别 test;类型 test-coverage): 删除 COMMON_GRAD_OFFLOAD、ACTOR_GRAD_OFFLOAD、CRITIC_GRAD_OFFLOAD 变量及命令行参数覆盖,是覆盖范围最大的测试配套。
tests/workers/config/test_engine_config_on_cpu.py(模块 配置测试;类别 test;类型 test-coverage;符号 test_offload_flags): offload 字段参数化测试移除 grad_offload,避免后续回归误覆盖失效字段。
tests/models/test_engine.py(模块 模型测试;类别 test;类型 test-coverage;符号 create_training_config): 训练配置创建 kwargs 移除 grad_offload=True,保证用例走有效配置。
关键符号:EngineConfig, McoreEngineConfig, MegatronEngine.init
关键源码片段
verl/workers/config/engine.py
删除 EngineConfig.grad_offload 字段并更新 McoreEngineConfig 文档,是本次配置契约变更的源头。
@dataclass
class EngineConfig(BaseConfig):
_mutable_fields = BaseConfig._mutable_fields | {
"use_dynamic_bsz",
"max_token_len_per_gpu",
"micro_batch_size_per_gpu",
"infer_max_token_len_per_gpu",
"infer_micro_batch_size_per_gpu",
"use_fused_kernels",
"use_remove_padding",
"forward_only",
"param_offload",
}
# 参数 offload 开关;开启后参数驻留 CPU,引擎空闲时同步释放梯度缓冲
param_offload: bool = False
# 优化器状态 offload 开关
optimizer_offload: bool = False
# grad_offload 已整体移除:此前仅被赋值给 MegatronEngine._is_offload_grad,
# 从未被任何逻辑消费,梯度缓冲生命周期已完全由 param_offload 管理
# 引擎是否仅做 forward(例如 ref policy)
forward_only: bool = False
verl/workers/engine/megatron/transformer_impl.py
移除 MegatronEngine.__init__ 中唯一的 _is_offload_grad 赋值,确认该标志在引擎层面从未被消费。
def __init__(
self,
model_config: HFModelConfig,
engine_config: McoreEngineConfig,
optimizer_config: McoreOptimizerConfig,
checkpoint_config: CheckpointConfig,
):
super().__init__()
self.model_config = model_config
self.engine_config = engine_config
self.optimizer_config = optimizer_config
self.checkpoint_config = checkpoint_config
assert self.engine_config.use_mbridge, "use_mbridge must be True"
_check_dcp_unsupported_features(self.engine_config, self.model_config)
self._init_device_mesh()
set_random_seed(seed=self.engine_config.seed)
# 参数 offload:控制参数是否驻留 CPU
self._is_offload_param = self.engine_config.param_offload
# 梯度缓冲的生命周期不再由独立开关控制,
# 引擎上下文会依照 param_offload 在闲置时释放梯度缓冲
# 优化器 offload:控制优化器状态是否驻留 CPU
self._is_offload_optimizer = self.engine_config.optimizer_offload
self.mode = None
verl/trainer/config/engine/megatron.yaml
Megatron 引擎默认配置模板,删除 grad_offload 键并更新 param_offload 注释,是用户直接可见的配置入口。
_target_: verl.workers.config.McoreEngineConfig
# 参数 offload 开关;引擎非活跃时同步释放梯度缓冲
param_offload: False
# 优化器状态 offload 开关
optimizer_offload: False
# tensor model parallel size
tensor_model_parallel_size: 1
# expert model parallel size
expert_model_parallel_size: 1
# pipeline model parallel size
pipeline_model_parallel_size: 1
# sequence parallel
sequence_parallel: True
# 是否使用 distributed optimizer
use_distributed_optimizer: True
评论区精华
PR 只有 1 条 comment,是作者 @wuxibin89 请求 review;审查阶段没有 review comments,wuxibin89 直接以 APPROVED 状态合并,未留下额外意见。由于 grad_offload 已被证明是死配置项,且 PR body 已自查同类 PR,评审过程没有出现争议或未解决问题。值得注意的点是改动被明确标记为 BREAKING,并同步清理了所有仓库内引用,这降低了评审成本。
风险与影响
- 风险:
- Breaking 配置契约:
EngineConfig 删除 grad_offload 字段后,任何仍通过 Hydra 配置、命令行覆盖或外部脚本引用该键的用户配置都会在 dataclass 实例化时报错,需要用户手动删除该键。仓库内 53 个文件已同步,但仓库外部 recipe、内部工具或用户自定义脚本可能存在遗漏引用。
- 配置同步面广:该改动需要与
_generated_*_megatron_trainer.yaml 等生成文件、示例脚本和文档保持同步;若后续其他 PR 重新引入类似开关,需要警惕配置与实例化检查脱节。
- 回归风险较低但存在:PR 声明
grad_offload 从未被消费,但主要验证集中在 CPU 配置测试与 shell 语法检查,缺少一次真实 GPU/NPU 训练 E2E 来最终确认 offload 路径无行为变化。由于没有运行时路径变更,此风险很低。
- 不涉及性能或安全问题,因为改动不影响运行时逻辑。
- 影响:对用户而言,使用 Megatron 后端并显式设置 grad_offload 的配置将在升级后加载失败,属于需要迁移的 Breaking 变更;使用默认配置或未引用该键的用户无感知。对代码库而言,配置面收敛为 param_offload + optimizer_offload,减少误导性配置项与文档负担,降低新用户误用成本。影响范围主要在配置层与 shell 脚本,不涉及训练/推理运行时热路径,整体影响面中等但影响深度较浅。
- 风险标记:Breaking 配置契约, 跨 53 文件同步, 外部引用风险, 低回归风险
关联脉络
- PR #7536 [cfg] fix: drop unused ref router replay config: 同系列配置死键清理:删除
ref.router_replay 并重新生成 flatten 配置,与本 PR 处理 grad_offload 的模式一致。
- PR #7466 [cfg, megatron, doc] fix: drop unused actor.router_replay in favor of engine config: 此前已删除
actor.router_replay 死键,本 PR 延续对 Megatron 配置面的收敛治理。
参与讨论