Prhub

#6562 [vllm, megatron] fix: mxfp8 trainning support on Ascend NPU

原始 PR 作者 quancs 合并时间 2026-06-04 15:41 文件变更 5 提交数 9 评论 5 代码增减 +52 / -3

执行摘要

修复 Ascend NPU 上 MXFP8 训练的多个问题

在 Ascend NPU 上使用 MXFP8 训练时,作者发现多个问题(详见 PR body,关联 Issue 缺失):(1)Megatron(MindSpeed)的 fp8_reuse_quantized_weight 功能要求在切换 actor/ref/actor_update 模型时重置量化上下文,否则权重状态错误;(2)rollout 后端 vllm-ascend 引用了不存在的 AscendQuantConfig 类,导致导入错误;(3)vllm-ascend 自动检测量化方式,即使在未指定 quantization 参数时也会将模型转换为低精度推理;(4)训练和推理对 TASK_QUEUE_ENABLE 环境变量的需求不同(训练可开启 level 2,推理只能 level 0 或 1),需要独立控制。

建议对 Ascend NPU 上运行 RL 训练的工程师阅读此 PR,尤其是 reset_fp8_reuse_quantized_weight 的设计(如何配合 fp8_reuse_quantized_weight 功能)、环境变量分离策略以及 to 方法的覆盖模式。这些模式可用于未来扩展其他后端。

讨论亮点

Review 中有两个核心讨论:

  • 防御性检查(gemini-code-assist[bot]):建议在 reset_fp8_reuse_quantized_weight 中添加 getattr 检查 override_transformer_configengine.mode 以防 AttributeError。作者已采纳并修改。
  • 环境变量功能说明(wuxibin89 提问,quancs 回答):VLLM_ASCEND_TASK_QUEUE_ENABLE 用于控制 Ascend NPU 的算子下发优化模式。训练可开启 TASK_QUEUE_ENABLE=2,但推理与图模式冲突,只能设 0 或 1。引入该变量可让训练环境保持 2,推理环境设为 1,避免冲突。

实现拆解

按照 4 个步骤实现:

  1. 新增 FP8 量化缓存重置函数:在 verl/workers/engine/mindspeed/utils.py 中定义 reset_fp8_reuse_quantized_weight(engine, device, model, optimizer, grad),该函数在启用 fp8_reuse_quantized_weight 配置时,调用 MindSpeed 的 clear_weight_quantization_reuse_cache 清除 NPU 上缓存的量化权重,并通过 set_weight_release_enabled 控制高精度权重的释放(仅 mode == 'train' 时释放)。函数内部使用 getattr 防御性获取 override_transformer_configengine.mode,避免 AttributeError
  2. 引擎类集成设备切换逻辑:在 verl/workers/engine/mindspeed/transformer_impl.py 中,为 MindspeedEngineWithLMHead(模型类型 language_model)和 MindSpeedMegatronEngineWithLMHead(backend=mindspeed_megatron)添加 to(device, model, optimizer, grad) 方法,在调用父类 to 方法前先执行 reset_fp8_reuse_quantized_weight,确保切换设备时正确重置量化上下文。同时将新函数导入到文件中。
  3. 禁用 vllm-ascend 量化自动检测并支持任务队列环境变量:在 verl/workers/rollout/vllm_rollout/vllm_async_server.pylaunch_servers 中,向 rollout server 的环境变量添加 VLLM_ASCEND_AUTO_DETECT_QUANTIZATION=0 以阻止自动检测;新增条件判断,当设置了 VLLM_ASCEND_TASK_QUEUE_ENABLE 环境变量时,将其值注入 rollout server 的 TASK_QUEUE_ENABLE 环境变量,从而允许训练和推理使用不同的任务队列模式。
  4. 移除不存在的 AscendQuantConfig 引用:在 verl/utils/vllm/vllm_fp8_utils.pyis_mxfp8_vllm_ascend 函数中,删除对 AscendQuantConfig 的导入和 isinstance 判断,仅保留 AscendModelSlimConfig 检查,避免导入错误。
  5. 调整基类 enter 顺序:在 verl/workers/engine/base.py__enter__ 方法中,将 self.engine.mode = self.mode 移到 _context_switch 之前,确保上下文切换时可访问正确的 mode 值(对 NPU 后端可能需要在 context 切换前设置 mode,以便重置函数获取到正确值)。
文件 模块 状态 重要度
verl/workers/engine/mindspeed/utils.py 引擎 modified 7.27
verl/workers/engine/mindspeed/transformer_impl.py 引擎 modified 6.96
verl/workers/rollout/vllm_rollout/vllm_async_server.py 推理 modified 5.35
verl/utils/vllm/vllm_fp8_utils.py 工具函数 modified 4.76
verl/workers/engine/base.py 引擎基类 modified 4.13

关键符号

reset_fp8_reuse_quantized_weight MindspeedEngineWithLMHead.to MindSpeedMegatronEngineWithLMHead.to

关键源码片段

verl/workers/engine/mindspeed/utils.py core-logic

新增核心函数 reset_fp8_reuse_quantized_weight,是修复 MXFP8 context 重置的关键。该函数使用 getattr 防御性检查,调用 MindSpeed 内部 API 清除量化缓存并控制高精度权重释放。

def reset_fp8_reuse_quantized_weight(engine, device: str, model: bool, optimizer: bool, grad: bool):
    """
    重置 FP8 复用量化权重状态,在设备切换或模式变更时调用。
    只对启用了 `fp8_reuse_quantized_weight` 的配置执行清除缓存和释放高精度权重的操作。
    """
    # 安全获取 override_transformer_config,避免在初始化时因属性不存在而崩溃
    override_config = getattr(engine.engine_config, "override_transformer_config", None)
    if override_config and override_config.get("fp8_reuse_quantized_weight", False):
        # 从 mindspeed 导入特定函数(延迟导入以避免循环依赖)
        from mindspeed.te.pytorch.fp8.reuse import (
            clear_weight_quantization_reuse_cache,
            set_weight_release_enabled,
        )
​
        # 清除 NPU 上缓存的量化权重,并释放存储
        clear_weight_quantization_reuse_cache(release_storage=True)
​
        # 仅在训练模式下释放高精度权重;对于 ref 模型,需要保留高精度权重用于 offloading;
        # 对于 actor_update 模型,高精度权重可能被释放,在 optimizer step 前恢复。
        set_weight_release_enabled(getattr(engine, "mode", None) == "train")
verl/workers/engine/mindspeed/transformer_impl.py core-logic

为两个 Mindspeed 引擎类添加 to 方法,在设备切换时调用 reset_fp8_reuse_quantized_weight,确保量化状态在模型移动前被正确处理。同时导入了新工具函数。

def to(self, device: str, model: bool = True, optimizer: bool = True, grad: bool = True):
    """
    手动将模型参数、优化器状态或两者移动到指定设备。
    注意此函数独立于 offload 配置。
    """
    # 在设备移动前重置 FP8 复用量化权重,确保 context 正确
    reset_fp8_reuse_quantized_weight(self, device, model, optimizer, grad)
    # 调用父类 to 方法执行实际设备移动
    super().to(device=device, model=model, optimizer=optimizer, grad=grad)# MindSpeedMegatronEngineWithLMHead 也实现了完全相同的 to 方法。

评论区精华

reset_fp8_reuse_quantized_weight 防御性检查 正确性

gemini-code-assist[bot] 建议在函数内使用 getattr 处理 override_transformer_config 可能为 None 的情况,并防御 engine.mode 未初始化的问题。

结论:作者已采纳建议,使用 getattr(engine.engine_config, "override_transformer_config", None) 和 getattr(engine, "mode", None) 进行安全访问。 · 已解决

VLLM_ASCEND_TASK_QUEUE_ENABLE 设计意图 question

wuxibin89 询问新增环境变量的用途。quancs 解释 TASK_QUEUE_ENABLE 是 Ascend NPU 的算子下发优化环境变量,训练可开 level 2,推理不能与图模式共存,因此需要独立控制。后续修改为引入 VLLM_ASCEND_TASK_QUEUE_ENABLE,由用户设置以统一控制推理侧的 TASK_QUEUE_ENABLE。

结论:引入独立环境变量 VLLM_ASCEND_TASK_QUEUE_ENABLE,当设置时将其值注入 rollout server 的 TASK_QUEUE_ENABLE 环境变量。 · 已解决

风险与影响

该 PR 主要影响 Ascend NPU 后端,CUDA 用户无影响。潜在风险包括:

  • 重置函数性能开销reset_fp8_reuse_quantized_weight 每次 to 调用时执行,如果频繁切换设备(如多模型并行),可能引入不必要的清除/释放开销。但仅在配置 fp8_reuse_quantized_weight 时生效,默认为 False。
  • 环境变量传递VLLM_ASCEND_TASK_QUEUE_ENABLE 通过 os.environ 读取,如果用户在启动 Python 进程后设置环境变量(而不是通过 shell export),可能无法被 Ray workers 正确读取,因为 Ray 的 runtime_env 是在创建 actor 时捕获的。不过这在 Ascend 文档中已有说明。
  • __enter__ 顺序调整:将 mode 设置移到 _context_switch 之前可能影响 CUDA 后端的某些依赖 mode 的 context 切换逻辑,但目前基类 _context_switch 不依赖 mode,风险低。
  • 缺少测试覆盖:没有伴随的单元测试或集成测试(PR 中测试项未勾选),难以确保修改的稳定性和回归。

此修复直接影响了 Ascend NPU 上使用 MXFP8 训练的 verl 用户,尤其是启用 fp8_reuse_quantized_weight 的 PPO/GRPO 训练流程。

  • 用户需在 shell 中设置 VLLM_ASCEND_TASK_QUEUE_ENABLE=1(推荐)以避免训练时 TASK_QUEUE_ENABLE=2 导致推理崩溃。
  • 对于不涉及量化的场景,新环境变量 VLLM_ASCEND_AUTO_DETECT_QUANTIZATION=0 会强制禁用量化自动检测,保障推理精度。
  • 移除 AscendQuantConfig 引用的部分不影响任何功能,因为该符号在 vllm-ascend 中已被删除。
  • 整体改动量小(+52/ -3),对非 Ascend 路径无侵入性。
Ascend 专用改动 核心路径变更 缺少测试覆盖 环境变量依赖性

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论