From 5b5eae23944e94f618895c05a69331bb06d1e3bd Mon Sep 17 00:00:00 2001 From: pmanczak Date: Tue, 11 Aug 2026 17:19:14 +0200 Subject: [PATCH] [Misc] Enable test_silu_mul_fp8_quant_deep_gemm on XPU (#49444) Signed-off-by: pmanczak Co-authored-by: Kunshang Ji --- .../moe/test_silu_mul_fp8_quant_deep_gemm.py | 27 +++++++++++-------- .../experts/batched_deep_gemm_moe.py | 9 +++---- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/tests/kernels/moe/test_silu_mul_fp8_quant_deep_gemm.py b/tests/kernels/moe/test_silu_mul_fp8_quant_deep_gemm.py index 6a5fad8262..e9a246f51b 100644 --- a/tests/kernels/moe/test_silu_mul_fp8_quant_deep_gemm.py +++ b/tests/kernels/moe/test_silu_mul_fp8_quant_deep_gemm.py @@ -23,6 +23,12 @@ from vllm.utils.math_utils import cdiv, round_up from vllm.utils.torch_utils import set_random_seed fp8_dtype = current_platform.fp8_dtype() +DEVICE = current_platform.device_type + +pytestmark = pytest.mark.skipif( + not (current_platform.is_cuda_alike() or current_platform.is_xpu()), + reason="persistent_masked_m_silu_mul_quant requires a CUDA-alike or XPU device.", +) CASES = [ (1, 1, 128, fp8_dtype), @@ -144,7 +150,7 @@ def pack_scales(x: torch.Tensor, tokens_per_expert: torch.Tensor) -> torch.Tenso # Add i32_padding here so we can view it as a i32 tensor later on. i32_padding = round_up(G, 4) - G - ref_s_i8 = torch.empty((E, T, G + i32_padding), dtype=torch.uint8, device="cuda") + ref_s_i8 = torch.empty((E, T, G + i32_padding), dtype=torch.uint8, device=DEVICE) for e in range(E): nt = tokens_per_expert[e].item() ref_s_i8[e, :nt, :G] = x[e, :nt].view(torch.int32) >> 23 @@ -177,9 +183,9 @@ def ref_with_scale_fmt( DeepGemmQuantScaleFMT.FLOAT32_CEIL_UE8M0, ] - ref_q = torch.empty((E, T, H), dtype=fp8_dtype, device="cuda") + ref_q = torch.empty((E, T, H), dtype=fp8_dtype, device=DEVICE) ref_s_f32 = torch.empty( - (E, T, cdiv(H, group_size)), dtype=torch.float32, device="cuda" + (E, T, cdiv(H, group_size)), dtype=torch.float32, device=DEVICE ) for e in range(E): @@ -202,7 +208,7 @@ def token_random(E, T, H2, tokens_per_expert): Initialize each token in a random range so we test a range of scale values. """ - y = torch.empty((E, T, H2), dtype=torch.bfloat16, device="cuda") + y = torch.empty((E, T, H2), dtype=torch.bfloat16, device=DEVICE) for e in range(E): for t in range(tokens_per_expert[e].item()): exp = random.choice(range(1, 20)) @@ -221,7 +227,7 @@ def test_silu_mul_fp8_quant_deep_gemm(E: int, T: int, H: int, fp8_type: torch.dt high=T, size=(E,), dtype=torch.int32, - device="cuda", + device=DEVICE, ) # Input tensor of shape (E, T, 2*H) @@ -288,12 +294,11 @@ def test_silu_mul_fp8_quant_deep_gemm(E: int, T: int, H: int, fp8_type: torch.dt for e in range(E): nt = tokens_per_expert[e].item() - if current_platform.is_rocm(): - # On ROCm the Triton fallback kernel uses f32 math - # intrinsics (tl.exp) that may differ from PyTorch's - # torch.exp by 1 ULP. At FP8 quantization - # boundaries this can flip one representable value. - # Allow 1 FP8 quantum of tolerance. + if current_platform.is_rocm() or current_platform.is_xpu(): + # ROCm and XPU both run the Triton fallback kernel, whose f32 + # math intrinsics (tl.exp) may differ from PyTorch's torch.exp + # by 1 ULP. At FP8 quantization boundaries this can flip one + # representable value. Allow 1 FP8 quantum of tolerance. torch.testing.assert_close( y_q[e, :nt].to(torch.float32), ref_y_q[e, :nt].to(torch.float32), diff --git a/vllm/model_executor/layers/fused_moe/experts/batched_deep_gemm_moe.py b/vllm/model_executor/layers/fused_moe/experts/batched_deep_gemm_moe.py index ce30afd5be..af9d170fcb 100644 --- a/vllm/model_executor/layers/fused_moe/experts/batched_deep_gemm_moe.py +++ b/vllm/model_executor/layers/fused_moe/experts/batched_deep_gemm_moe.py @@ -211,16 +211,13 @@ def persistent_masked_m_silu_mul_quant( DeepGemmQuantScaleFMT.UE8M0, ] - device_capability = current_platform.get_device_capability() - assert device_capability is not None - cuda_arch = device_capability.to_int() - - if current_platform.is_cuda() and cuda_arch >= 80: + # The C++ kernel requires sm_80+; ROCm and XPU take the Triton path below. + if current_platform.is_cuda() and current_platform.has_device_capability(80): torch.ops._C.persistent_masked_m_silu_mul_quant( y, tokens_per_expert, y_q, y_s, ceil_ue8m0 ) else: - # Triton fallback for ROCm -- the C++ kernel is guarded by + # Triton fallback for ROCm and XPU -- the C++ kernel is guarded by # #ifndef USE_ROCM in activation_kernels.cu. # https://github.com/ROCm/aiter/issues/2420 stride_cnt_e = tokens_per_expert.stride()[0]