Prhub

#38083 [Bugfix] Fix DeepGemm E8M0 accuracy degradation for Qwen3.5 FP8 on Blackwell

原始 PR 作者 vadiklyutiy 合并时间 2026-03-26 16:21 文件变更 10 提交数 5 评论 9 代码增减 +69 / -11

执行摘要

修复 Qwen3.5 FP8 在 Blackwell 上 DeepGemm 精度下降

Issue #37804 报告 Qwen3.5-35B-A3B-FP8 在 Blackwell (B200) 上 GSM8K 精度从 ~0.81 下降至 ~0.69。根本原因是 DeepGemm 强制使用的 E8M0 格式每层损失约 0.4-0.5 bits 精度,累积约 80 层。禁用 DeepGemm 后精度恢复至 ~0.81。

值得精读,尤其关注配置层 use_deep_gemm 的三态设计与自动禁用机制的权衡。review 中提出的覆盖失败和虚假日志问题需后续 PR 修复,可作为实践参考。

讨论亮点

gemini-code-assist[bot]:指出 input_quant_fp8.pyself.use_ue8m0 条件可能冗余,因为 DeepGemmQuantScaleFMT.from_oracle() == UE8M0 已覆盖,建议简化,但 PR 未处理。

claude[bot]:指出 fp8.py 中 MoE 层未正确禁用,因为 Fp8MoEMethod 未读取 quant_config.use_deep_gemm。作者回复「只想禁用 gemm,不打算禁用 DeepGemm 的 MoE」,MoE 层使用不同后端,不受影响,设计意图明确。

claude[bot]:指出自动禁用无法被 VLLM_USE_DEEP_GEMM=1 覆盖,且 should_auto_disable_deep_gemm 未检查 is_deep_gemm_supported(),在 DeepGemm 未安装时仍返回 True 导致误导性警告。这两个问题在合并时仍未解决。

实现拆解

  1. 定义排除列表和检查函数:在 vllm/utils/deep_gemm.py 中新增 _DEEPGEMM_BLACKWELL_EXCLUDED_MODEL_TYPES 集合(含 qwen3_5_text, qwen3_5_moe_text)和 should_auto_disable_deep_gemm 函数,该函数检查当前平台是否为 Blackwell (SM100) 以及模型类型是否在排除列表中。

  2. 在配置初始化时自动禁用:在 vllm/config/vllm.pyVllmConfig.__post_init__ 中,当 quant_config.use_deep_gemmNone(未手动设置)时,调用上述函数决定是否禁用,并记录警告日志。禁用后设置 quant_config.use_deep_gemm = False

  3. 将禁用信号传递给 FP8 线性方法:在 vllm/model_executor/layers/quantization/fp8.pyFp8Config 中新增 use_deep_gemm: bool | None = None 字段。在 Fp8LinearMethod.__init__ 中根据此字段决定是否使用 DeepGemm,而不是仅依赖全局检测。同时将 use_deep_gemm 传递给 W8A8BlockFp8LinearOp

  4. 确保块量化后处理跳过:在 Fp8LinearMethod.process_weights_after_loading 中,仅在 self.use_deep_gemm 为真时执行 maybe_post_process_fp8_weight_block,避免不必要的 UE8M0 权重预转换。

  5. 更新 GSM8K 测试配置:新增 Qwen3.5-397B-A17B-NVFP4 测试配置(tests/evals/gsm8k/configs/Qwen3.5-397B-A17B-NVFP4-DEP2.yaml),更新 Qwen3.5-35B-A3B-FP8Qwen3.5-35B-A3B 的预期精度和容忍度。测试脚本 test_gsm8k_correctness.py 改为从配置动态加载容忍度。

文件 模块 状态 重要度
vllm/utils/deep_gemm.py DeepGemm 配置 modified 6.79
vllm/config/vllm.py 全局配置 modified 6.29
vllm/model_executor/layers/quantization/fp8.py FP8 量化 modified 6.09
vllm/model_executor/layers/quantization/utils/fp8_utils.py 块 FP8 算子 modified 5.56
tests/evals/gsm8k/configs/Qwen3.5-397B-A17B-NVFP4-DEP2.yaml GSM8K 测试 added 4.48
tests/evals/gsm8k/test_gsm8k_correctness.py GSM8K 测试 modified 4.27

关键符号

should_auto_disable_deep_gemm VllmConfig.__post_init__ Fp8Config.__init__ Fp8LinearMethod.__init__ Fp8LinearMethod.process_weights_after_loading W8A8BlockFp8LinearOp.__init__

关键源码片段

vllm/utils/deep_gemm.py core-logic

新增排除列表和自动禁用检查函数,是修复的核心决策点

# 文件:vllm/utils/deep_gemm.py# 在 Blackwell 上已知因 DeepGemm E8M0 精度下降而需要禁用 DeepGemm 的模型类型集合
_DEEPGEMM_BLACKWELL_EXCLUDED_MODEL_TYPES: set[str] = {
    "qwen3_5_text",
    "qwen3_5_moe_text",
}def should_auto_disable_deep_gemm(model_type: str | None) -> bool:
    """检查是否应该为给定模型在 Blackwell 上自动禁用 DeepGemm。    如果模型类型已知在 Blackwell GPU (SM100+ 系列) 上使用 DeepGemm E8M0 格式
    会导致精度下降,则返回 True。
    """
    # 如果模型类型为 None,无法判断
    if model_type is None:
        return False
    # 仅针对 Blackwell (SM100 系列 ) GPU
    if not current_platform.is_device_capability_family(100):
        return False
    # 检查模型类型是否在排除列表中
    return model_type in _DEEPGEMM_BLACKWELL_EXCLUDED_MODEL_TYPES
vllm/config/vllm.py dependency-wiring

在配置初始化中连接自动禁用逻辑,确保在用量化前决策

# 文件:vllm/config/vllm.py ( 部分 )
​
        # 如果量化配置已加载且 `use_deep_gemm` 尚未被设置,则检查是否需要自动禁用
        if (
            self.quant_config is not None
            and self.model_config is not None
            and hasattr(self.quant_config, "use_deep_gemm")
            and self.quant_config.use_deep_gemm is None # 仅当未手工设置时
        ):
            from vllm.utils.deep_gemm import should_auto_disable_deep_gemm
​
            model_type = getattr(
                self.model_config.hf_text_config, "model_type", None
            )
            if should_auto_disable_deep_gemm(model_type):
                self.quant_config.use_deep_gemm = False
                logger.warning_once(
                    "Auto-disabled DeepGemm for model_type=%s on Blackwell. "
                    "DeepGemm E8M0 scale format causes accuracy degradation "
                    "for this architecture. Falling back to CUTLASS. "
                    "To disable DeepGemm globally, set VLLM_USE_DEEP_GEMM=0.",
                    model_type,
                )
vllm/model_executor/layers/quantization/fp8.py data-contract

数据契约变更:新增 use_deep_gemm 字段并在线性方法中使用

# 文件:vllm/model_executor/layers/quantization/fp8.py ( 部分 )
​
    def __init__(self, quant_config: Fp8Config):
        self.quant_config = quant_config
        self.cutlass_block_fp8_supported = cutlass_block_fp8_supported()
        self.out_dtype = torch.get_default_dtype()
        self.marlin_input_dtype = None
        self.use_aiter_and_is_supported = rocm_aiter_ops.is_linear_fp8_enabled()
        # 如果量化配置指定了 use_deep_gemm,则使用该值;否则自动检测
        if self.quant_config.use_deep_gemm is not None:
            self.use_deep_gemm = self.quant_config.use_deep_gemm
        else:
            self.use_deep_gemm = is_deep_gemm_supported()
​
        self.weight_block_size = self.quant_config.weight_block_size
        self.block_quant = self.weight_block_size is not None
        # ... 后续 init_fp8_linear_kernel 调用

评论区精华

input_quant_fp8.py 中 self.use_ue8m0 条件冗余 style

gemini-code-assist[bot] 指出新增的 self.use_ue8m0 条件与 DeepGemmQuantScaleFMT.from_oracle() == UE8M0 重复,可能应移除以简化逻辑。

结论:PR 未对此做出修改,评论未解决。 · unresolved

MoE 层 DeepGemm 禁用不完整 设计

claude[bot] 指出 Fp8MoEMethod 未读取 quant_config.use_deep_gemm,路由层仍可能使用 DeepGemm。作者回应意图仅禁用 gemm 层,MoE 层使用不同后端 (FLASHINFER_TRTLLM),不受影响。

结论:作者明确设计意图,不修改。 · 已解决

自动禁用无法被 VLLM_USE_DEEP_GEMM=1 覆盖 正确性

claude[bot] 指出 PR 描述声称环境变量可覆盖,但实际仅在未设置时生效;设 VLLM_USE_DEEP_GEMM=1 无法强制启用。

结论:未解决,PR 中没有提供强制启用机制。 · unresolved

should_auto_disable_deep_gemm 在 DeepGemm 未安装时误触发 正确性

claude[bot] 指出函数未检查 is_deep_gemm_supported(),导致即使 DeepGemm 不可用也会返回 True 并发出误导性警告。

结论:未解决,PR 未添加该检查。 · unresolved

风险与影响

  • 精度回归风险:排除列表仅包含 Qwen3.5 模型类型,其他如 minimax 等 FP8 密集模型若同样受 E8M0 影响,精度问题可能未被覆盖。
  • 覆盖机制缺陷VLLM_USE_DEEP_GEMM=1 无法强制启用 DeepGemm,用户若希望为 Qwen3.5 启用 DeepGemm 测试无途径。
  • 误导日志:当 DeepGemm 未安装时,should_auto_disable_deep_gemm 仍返回 True,配置层会打印“Auto-disabled DeepGemm”警告,实际上 DeepGemm 不可用,可能混淆用户。
  • 性能影响:回退到 CUTLASS 可能降低推理吞吐,但精度恢复是首要目标。
  • MoE 层风险:MoE 路由层未禁用 DeepGemm,但作者认为其不受影响;若 MoE 层也受 E8M0 影响,精度恢复将不完整。

用户:Qwen3.5 FP8 模型在 Blackwell 上精度回归得到修复(GSM8K 均值从 0.69 恢复至 0.80),但推理速度可能下降(回退到 CUTLASS)。

系统:配置初始化路径增加模型类型检查,启动时间影响可忽略。use_deep_gemm 的三态设计(None/True/False)提供了灵活性。

团队:需维护排除列表以适配未来出现类似问题的模型。Blackwell CI 新增 Qwen3.5-397B 测试,加强了回归保护。

排除模型列表有限(仅 Qwen3.5) 自动禁用覆盖机制不完整 虚假日志警告(当 DeepGemm 未安装时) 潜在性能下降(回退 CUTLASS)

关联 Issue

#37804 [Bug] DeepGemm E8M0 scale format causes accuracy degradation for Qwen3.5 FP8 on Blackwell

完整报告

参与讨论