Prhub

#49747 [MXFP8][ROCm] Fix MXFP8 MoE backend selection

原始 PR 作者 fxmarty-amd 合并时间 2026-07-29 07:57 文件变更 6 提交数 6 评论 10 代码增减 +244 / -61

执行摘要

修复 MXFP8 MoE 后端选择与 alpha/beta 硬编码

修复了 AMD MI355 CI 中长期失败的 test_mxfp8_logprobs[moe] 测试。错误原因:AITER_MXFP8 后端错误分配给不符合条件的模型(如激活类型不是 SwiGLU-OAI 的模型),以及 TRITON_MXFP8 和 EMULATION 后端中错误地硬编码了 SwiGLU alpha=1.702 和 beta=1.0,忽略了模型配置提供的值。

建议精读此 PR,它展示了如何通过 is_supported_config 实现后端准入检查,以及如何将平台特定的回退逻辑融入统一选择框架。这种模式值得在支持多后端的量化模块中推广。

讨论亮点

Review 中 tjtanaa 指出:原 ROCm 回退逻辑针对 gfx942(Emulation)和 gfx950(TRITON_MXFP8)做了区分,但此 PR 删除该函数后,需要确认自动选择循环能否正确处理。作者 fxmarty-amd 回复:is_supported_config 已经通过设备检查(current_platform.supports_mx())覆盖了这些区分,因此统一循环是安全的,并更新了测试用例来明确验证。最终双方达成一致。

实现拆解

  1. AITER 后端增加激活与参数校验:在 AiterMxfp8Experts.is_supported_config 中新增条件判断,当传入的 activation 不是 SWIGLUOAI_UNINTERLEAVEswiglu_alpha/swiglu_beta 与硬编码值 (1.702, 1.0) 不匹配时,返回 (False, reason),从而阻止 AITER 后端被错误选中。
  2. Triton/Emulation 后端使用模型参数:在 Mxfp8NativeTritonExperts.applyMxfp8EmulationTritonExperts.activation 中移除硬编码的 alpha=1.702, beta=1.0,改为从 self.gemm1_alphaself.gemm1_beta 读取,这些值由基类 TritonExperts.__init__FusedMoEConfig 构造时设置。
  3. Oracle 重构:统一选择循环:在 oracle/mxfp8.py 中,将 TRITON_MXFP8EMULATION 加入 _SUPPORTED_BACKENDS(优先级队列),删除专用回退函数 _select_rocm_mxfp8_backend,使 select_mxfp8_moe_backend 统一遍历所有后端,由各自的 is_supported_config 决定是否可用。
  4. 测试配套:在 test_mxfp8.py 中新增三个端到端测试(激活拒绝、参数拒绝、参数接受);在 test_mxfp8_aiter_backend_selection.py 中调整夹具配置匹配新约束,新增 test_gfx950_picks_aitertest_gfx942_picks_triton 验证自动选择行为。
文件 模块 状态 重要度
tests/models/quantization/test_mxfp8.py E2E 测试 modified 7.02
vllm/model_executor/layers/fused_moe/oracle/mxfp8.py 后端选择器 modified 7.34
vllm/model_executor/layers/fused_moe/experts/aiter_mxfp8_moe.py AITER 内核 modified 6.9
tests/kernels/moe/test_mxfp8_aiter_backend_selection.py 选择器测试 modified 6.01
vllm/model_executor/layers/fused_moe/experts/mxfp8_native_moe.py 原生内核 modified 6.09
vllm/model_executor/layers/fused_moe/experts/mxfp8_emulation_moe.py 仿真内核 modified 6.05

关键符号

select_mxfp8_moe_backend _select_rocm_mxfp8_backend AiterMxfp8Experts.is_supported_config Mxfp8NativeTritonExperts.apply Mxfp8EmulationTritonExperts.activation test_mxfp8_aiter_requires_swigluoai_activation test_mxfp8_aiter_requires_swigluoai_params test_mxfp8_aiter_accepts_swigluoai_params test_gfx950_picks_aiter test_gfx942_picks_triton

关键源码片段

tests/models/quantization/test_mxfp8.py test-coverage

新增 3 个端到端测试覆盖 AITER 后端激活类型和 alpha/beta 校验的拒绝 / 接受场景,确保后端选择行为正确。

@pytest.mark.skipif(
    not is_quant_method_supported("mxfp8"),
    reason="mxfp8 is not supported on this GPU type (requires sm_100+).",
)
@pytest.mark.skipif(
    not current_platform.is_rocm(),
    reason="AITER MXFP8 MoE backend is ROCm-only.",
)
@pytest.mark.quant_model
def test_mxfp8_aiter_requires_swigluoai_activation(
    monkeypatch: pytest.MonkeyPatch,
) -> None:
    # 从 vllm 内部模块导入所需类和配置
    from vllm.model_executor.layers.fused_moe.activation import MoEActivation
    from vllm.model_executor.layers.fused_moe.config import (
        FusedMoEConfig, FusedMoEParallelConfig, RoutingMethodType,
    )
    from vllm.model_executor.layers.fused_moe.experts import aiter_mxfp8_moe
    from vllm.model_executor.layers.fused_moe.oracle.mxfp8 import (
        select_mxfp8_moe_backend,
    )
​
    # 模拟 gfx950 环境:强制设备检查和 flydsl 可用性通过
    monkeypatch.setattr(
        aiter_mxfp8_moe.AiterMxfp8Experts,
        "_supports_current_device",
        staticmethod(lambda: True),
    )
    monkeypatch.setattr(
        aiter_mxfp8_moe,
        "is_aiter_mxfp8_moe_available",
        lambda: True,
    )
​
    # 构造一个激活类型为 SILU 的 MoE 配置,故意不与 AITER 要求的 SWIGLUOAI 匹配
    config = FusedMoEConfig(
        num_experts=8,
        experts_per_token=2,
        hidden_dim=256,
        intermediate_size=256,
        num_local_experts=8,
        num_logical_experts=8,
        moe_parallel_config=FusedMoEParallelConfig.make_no_parallel(),
        activation=MoEActivation.SILU,
        in_dtype=torch.bfloat16,
        device="cuda",
        routing_method=RoutingMethodType.Renormalize,
        moe_backend="aiter",
    )
​
    # 期望 select_mxfp8_moe_backend 抛出 ValueError,提示需要 swigluoai_uninterleave 激活
    with pytest.raises(ValueError, match="requires activation=swigluoai_uninterleave"):
        select_mxfp8_moe_backend(config)
vllm/model_executor/layers/fused_moe/oracle/mxfp8.py core-logic

重构后端选择逻辑,将 TRITON_MXFP8 和 EMULATION 纳入自动选择循环,删除冗余的 ROCm 专用回退函数,统一选择路径。

def select_mxfp8_moe_backend(
    config: FusedMoEConfig,
) -> tuple[Fp8MoeBackend, type[mk.FusedMoEExperts]]:
    """选择 MXFP8 MoE 后端和最佳专家类。    Returns:
        一个元组 (fp8_backend, experts_cls)。
    """
    runner_backend = config.moe_backend
    if runner_backend != "auto":
        # 用户显式指定了后端,直接映射并验证
        backend = _BACKEND_NAME_MAP.get(runner_backend)
        if backend is None:
            raise ValueError(
                f"moe_backend='{runner_backend}' is not supported for "
                f"MXFP8 MoE. Expected one of "
                f"{list(_BACKEND_NAME_MAP.keys())}."
            )
        logger.info_once(
            "Using '%s' MxFp8 MoE backend (user-requested).",
            backend.value,
        )
        return backend, _select_kernel_cls(backend, config)
​
    # 自动选择:按优先级遍历 _SUPPORTED_BACKENDS,
    # 每个后端通过 is_supported_config 检查是否适合当前配置
    for backend in _SUPPORTED_BACKENDS:
        try:
            experts_cls = _select_kernel_cls(backend, config)
        except ValueError:
            continue # 不支持则跳过,尝试下一个
        logger.info_once("Using '%s' MxFp8 MoE backend.", backend.value)
        return backend, experts_cls
​
    raise ValueError("No MXFP8 MoE backends available.")
vllm/model_executor/layers/fused_moe/experts/aiter_mxfp8_moe.py core-logic

在 is_supported_config 中增加激活类型和 alpha/beta 的校验,确保只有 MiniMax M3 等符合要求的模型才能使用 AITER 后端。

# 定义 AITER 后端硬编码的 SwiGLU-OAI 参数
_AITER_SWIGLU_ALPHA = 1.702
_AITER_SWIGLU_BETA = 1.0@staticmethod
def is_supported_config(
    cls, moe_config, weight_key, activation_key, activation_format
):
    # 先调用父类检查基础条件(设备、数据格式等)
    is_supported, reason = super().is_supported_config(
        cls, moe_config, weight_key, activation_key, activation_format
    )
​
    # 如果父类认为不支持,直接返回父类结果
    if not is_supported:
        return is_supported, reason
​
    # 检查 flydsl 包是否安装
    if not is_aiter_mxfp8_moe_available():
        return False, (
            "kernel requires the aiter flydsl package, which is not installed"
        )
​
    # 检查激活类型必须是 SWIGLUOAI_UNINTERLEAVE
    if moe_config.activation != MoEActivation.SWIGLUOAI_UNINTERLEAVE:
        return False, (
            "kernel hardcodes SwiGLU-OAI activation and requires "
            f"activation={MoEActivation.SWIGLUOAI_UNINTERLEAVE.value}; "
            f"got activation={moe_config.activation.value}"
        )
​
    # 检查 alpha/beta 是否与硬编码值一致
    if (moe_config.swiglu_alpha is None
        or not math.isclose(float(moe_config.swiglu_alpha), _AITER_SWIGLU_ALPHA)
        or moe_config.swiglu_beta is None
        or not math.isclose(float(moe_config.swiglu_beta), _AITER_SWIGLU_BETA)):
        return False, (
            "kernel hardcodes SwiGLU-OAI with "
            f"alpha={_AITER_SWIGLU_ALPHA} and beta={_AITER_SWIGLU_BETA}; "
            f"got swiglu_alpha={moe_config.swiglu_alpha} and "
            f"swiglu_beta={moe_config.swiglu_beta}"
        )
​
    return True, reason

评论区精华

删除 _select_rocm_mxfp8_backend 后 gfx942/gfx950 的区分处理 设计

tjtanaa 指出原 ROCm 回退逻辑针对 gfx942(Emulation)和 gfx950(TRITON_MXFP8)做了区分,删除后需要确认自动选择循环能正确处理。fxmarty-amd 回复说 is_supported_config 已经通过设备检查(current_platform.supports_mx())覆盖了这些区分,并更新了测试用例来明确验证。

结论:作者确认 is_supported_config 已足够,统一循环是安全的,测试已补充。 · 已解决

CI 中 MoE 测试失败 other

jikunshang 报告该 PR 导致 AMD CI 中 `Kernels MoE Test 1` 和 `Test 3` 失败,并提供 CI 链接。fxmarty-amd 致歉并确认后续提交 #50222 修复了问题。

结论:问题在后续 PR #50222 中修复。 · 已解决

风险与影响

主要风险在于后端选择逻辑重构后,自动降级行为可能改变。例如,若之前 AITER_MXFP8 后端由于未通过 activation 检查而被跳过,现在会继续尝试 TRITON_MXFP8EMULATION,这可能导致某些模型之前在 ROCm 上因无可用后端而报错,现在却能自动降级为 Triton 或 Emulation 后端,这实际上是预期改进。另一个风险是 TritonExperts.__init__ 中设置的 gemm1_alpha/gemm1_beta 可能因配置缺失而为 None,但代码中有回退逻辑(TritonExperts.__init__ 会设置默认值 1.702/1.0),因此风险较低。整体回归风险可控。

直接影响所有在 AMD ROCm 平台上使用 MXFP8 量化(特别是 --quantization mxfp8)的 MoE 模型。修正后,MiniMax M3 模型(激活为 SWIGLUOAI_UNINTERLEAVE)能正确选用 AITER 后端;其他模型(如 OLMoE,激活为 SILU)会自动降级到 Triton 或 Emulation 后端,且 alpha/beta 使用模型配置值,推断质量更准确。间接影响是后端选择代码更清晰统一,便于未来添加新后端。

后端选择逻辑重构 ROCm 特定路径 自动降级行为变更 后续修复 PR #50222

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论