[Bugfix][ROCm][MoE] Fall back instead of crashing when AITER MoE is requested for a non-gated (is_act_and_mul=False) model (#56590)

Signed-off-by: Shantipriya Parida <shantipriya.parida@amd.com>
This commit is contained in:
Shantipriya Parida
2026-09-17 13:39:26 +00:00
committed by GitHub
parent fe284ea17d
commit 0eae9acd4d
2 changed files with 87 additions and 1 deletions
@@ -6,6 +6,7 @@ import pytest
import torch
from tests.kernels.moe.utils import make_dummy_moe_config
from vllm.model_executor.layers.fused_moe.activation import MoEActivation
from vllm.model_executor.layers.fused_moe.config import RoutingMethodType
from vllm.model_executor.layers.fused_moe.oracle.unquantized import (
UnquantizedMoeBackend,
@@ -228,6 +229,65 @@ def test_select_rocm_aiter_backend(mock_aiter_enabled, mock_has_flashinfer):
assert expert_cls is not None
@patch(
"vllm.utils.flashinfer.has_flashinfer",
return_value=False,
)
@patch(
"vllm.model_executor.layers.fused_moe.oracle.unquantized.rocm_aiter_ops."
"is_fused_moe_enabled",
return_value=True,
)
@patch(
"vllm.model_executor.layers.fused_moe.oracle.unquantized.rocm_aiter_ops."
"is_rdna_aiter_enabled",
return_value=False,
)
@pytest.mark.skipif(
not current_platform.is_rocm(), reason="ROCm-specific backend selection test"
)
def test_select_rocm_aiter_backend_non_gated_activation_falls_back(
mock_rdna_disabled, mock_aiter_enabled, mock_has_flashinfer, monkeypatch
):
"""Test ROCm backend selection falls back (not raises) for non-gated MoE."""
monkeypatch.setenv("VLLM_ROCM_USE_AITER", "1")
monkeypatch.setenv("VLLM_ROCM_USE_AITER_MOE", "1")
with patch(
"vllm.model_executor.layers.fused_moe.oracle.unquantized.current_platform"
) as mock_platform:
mock_platform.is_cuda.return_value = False
mock_platform.is_rocm.return_value = True
mock_platform.is_cpu.return_value = False
mock_platform.is_xpu.return_value = False
mock_platform.is_tpu.return_value = False
mock_platform.is_out_of_tree.return_value = False
moe_config = make_dummy_moe_config(activation=MoEActivation.SILU_NO_MUL)
assert moe_config.is_act_and_mul is False
selected_backend, expert_cls = select_unquantized_moe_backend(
moe_config=moe_config,
)
assert selected_backend != UnquantizedMoeBackend.AITER
assert expert_cls is not None
@pytest.mark.skipif(
not current_platform.is_rocm(), reason="ROCm-specific backend selection test"
)
def test_explicit_aiter_backend_non_gated_activation_still_raises():
"""Explicit `--moe-backend aiter` still raises for non-gated MoE;
only the env-var opt-in path falls back."""
moe_config = make_dummy_moe_config(activation=MoEActivation.SILU_NO_MUL)
moe_config.moe_backend = "aiter" # explicit pin, not "auto"
assert moe_config.is_act_and_mul is False
with pytest.raises(ValueError):
select_unquantized_moe_backend(moe_config=moe_config)
@patch(
"vllm.model_executor.layers.fused_moe.experts.trtllm_bf16_moe.TrtLlmBf16ExpertsMonolithic.is_supported_config",
return_value=(True, None),
@@ -305,7 +305,33 @@ def select_unquantized_moe_backend(
AVAILABLE_BACKENDS.remove(UnquantizedMoeBackend.AITER)
else:
backend = UnquantizedMoeBackend.AITER
return _return_or_raise(backend, moe_config, activation_format)
reason = None
for k_cls in backend_to_kernel_cls(backend):
supported, reason = k_cls.is_supported_config(
k_cls, moe_config, None, None, activation_format
)
if supported:
logger.info_once(_make_log_backend(backend))
return backend, k_cls
# AITER was explicitly requested but does not support this
# deployment configuration (e.g. a non-gated MoE activation,
# which AiterExperts._supports_no_act_and_mul() rejects
# unconditionally). Rather than hard-crashing at engine init,
# warn — explicitly stating that this is falling back, and
# which backends will be tried next — and fall back to the
# remaining backends in priority order below.
logger.warning_once(
"VLLM_ROCM_USE_AITER_MOE=1 was requested, but %s "
"Falling back to try the remaining available MoE backends: %s.",
_make_log_unsupported(backend, reason),
", ".join(
b.value
for b in AVAILABLE_BACKENDS
if b != UnquantizedMoeBackend.AITER
),
)
if UnquantizedMoeBackend.AITER in AVAILABLE_BACKENDS:
AVAILABLE_BACKENDS.remove(UnquantizedMoeBackend.AITER)
for backend in AVAILABLE_BACKENDS:
for k_cls in backend_to_kernel_cls(backend):