# PR #7544 完整报告

- 仓库：`verl-project/verl`
- 标题：[BREAKING][megatron, cfg] fix: remove unused grad_offload
- 合并时间：2026-08-25 19:12
- 原文链接：http://prhub.com.cn/verl-project/verl/pull/7544

---

# 执行摘要

- 一句话：移除失效 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，随后逐层清理引用。

1. **配置层清理**：删除 `EngineConfig.grad_offload: bool = False` 字段及其注释，并在 `McoreEngineConfig` 文档字符串中把 `param_offload` 的语义扩展为“offload 参数到 CPU，并在引擎非活跃时释放梯度缓冲”。
2. **引擎层收敛**：在 `verl/workers/engine/megatron/transformer_impl.py` 的 `MegatronEngine.__init__` 中删除 `self._is_offload_grad = self.engine_config.grad_offload`，初始化只保留 `_is_offload_param` 与 `_is_offload_optimizer`。
3. **示例与测试覆盖删除**：从 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=$...` 等参数。
4. **生成配置与文档同步**：重新生成 `verl/trainer/config/_generated_ppo_megatron_trainer.yaml` 等扁平配置，修改 `verl/trainer/config/engine/megatron.yaml` 删除 `grad_offload` 键并更新 `param_offload` 注释，同时更新相关文档说明。
5. **测试验证**：更新 `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` 文档，是本次配置契约变更的源头。

```python
@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` 赋值，确认该标志在引擎层面从未被消费。

```python
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` 注释，是用户直接可见的配置入口。

```yaml
_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，并同步清理了所有仓库内引用，这降低了评审成本。

- 暂无高价值评论线程

# 风险与影响

- 风险：
 1. **Breaking 配置契约**：`EngineConfig` 删除 `grad_offload` 字段后，任何仍通过 Hydra 配置、命令行覆盖或外部脚本引用该键的用户配置都会在 dataclass 实例化时报错，需要用户手动删除该键。仓库内 53 个文件已同步，但仓库外部 recipe、内部工具或用户自定义脚本可能存在遗漏引用。
 2. **配置同步面广**：该改动需要与 `_generated_*_megatron_trainer.yaml` 等生成文件、示例脚本和文档保持同步；若后续其他 PR 重新引入类似开关，需要警惕配置与实例化检查脱节。
 3. **回归风险较低但存在**：PR 声明 `grad_offload` 从未被消费，但主要验证集中在 CPU 配置测试与 shell 语法检查，缺少一次真实 GPU/NPU 训练 E2E 来最终确认 offload 路径无行为变化。由于没有运行时路径变更，此风险很低。
 4. 不涉及性能或安全问题，因为改动不影响运行时逻辑。
 - 影响：对用户而言，使用 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 配置面的收敛治理。