[Perf][NPU] Enable native GQA & fused AddNorm for MiniMax-H3 encoder (#6040)

Signed-off-by: MarkPoloChina <1228479724@qq.com>
Signed-off-by: XiongZhongwei <1228479724@qq.com>
This commit is contained in:
XiongZhongwei authored and GitHub committed 2026-08-26 09:14:05 +08:00
1 parent a708ae5b7a
commit 40dcfdbb43
11 files changed
+520 -28

No files matched your search

+91
View File
@@ -340,6 +340,97 @@ def test_rmsnorm_npu_receives_gamma_with_configured_dtype(monkeypatch: pytest.Mo
assert captured["epsilon"].item() == pytest.approx(1e-5)
# ── RMSNorm residual tests ──
def test_rmsnorm_matches_native_residual_contract():
"""The non-NPU path preserves separate residual-add and RMSNorm math."""
from vllm_omni.diffusion.layers.norm import RMSNorm
eps = 1e-6
norm = RMSNorm(4, eps=eps, dtype=torch.bfloat16)
norm.weight.data.copy_(torch.tensor([1.0, 0.5, 1.5, 2.0], dtype=torch.bfloat16))
x = torch.tensor([[1.0, -2.0, 3.0, -4.0]], dtype=torch.bfloat16)
residual = torch.tensor([[0.00390625, 0.0078125, -0.0078125, 0.015625]], dtype=torch.bfloat16)
expected_residual = residual + x
expected_fp32 = expected_residual.float()
expected_output = expected_fp32 * torch.rsqrt(expected_fp32.square().mean(-1, keepdim=True) + eps)
expected_output = (expected_output * norm.weight.float()).to(x.dtype)
output, updated_residual = norm.forward_native(x, residual)
torch.testing.assert_close(updated_residual, expected_residual, atol=0, rtol=0)
torch.testing.assert_close(output, expected_output, atol=0, rtol=0)
@pytest.mark.parametrize(
"forward_name",
["forward_cuda", "forward_hip", "forward_musa", "forward_xpu"],
)
def test_rmsnorm_non_npu_residual_delegates_to_native(
monkeypatch: pytest.MonkeyPatch,
forward_name: str,
):
"""Platform wrappers keep residual arithmetic in forward_native."""
from vllm_omni.diffusion.layers.norm import RMSNorm
norm = RMSNorm(4, eps=1e-5, dtype=torch.bfloat16)
x = torch.randn(2, 4, dtype=torch.bfloat16)
residual = torch.randn_like(x)
expected_output = torch.randn_like(x)
expected_residual = torch.randn_like(x)
captured: dict[str, object] = {}
def forward_native(native_x: torch.Tensor, native_residual: torch.Tensor | None = None):
captured.update(x=native_x, residual=native_residual)
return expected_output, expected_residual
monkeypatch.setattr(norm, "forward_native", forward_native)
output, updated_residual = getattr(norm, forward_name)(x, residual)
assert output is expected_output
assert updated_residual is expected_residual
assert captured["x"] is x
assert captured["residual"] is residual
def test_rmsnorm_npu_residual_uses_torch_npu_fused_op(monkeypatch: pytest.MonkeyPatch):
"""NPU keeps the direct fused AddRMSNorm path instead of IR fallback."""
from vllm_omni.diffusion.layers.norm import RMSNorm
captured: dict[str, object] = {}
fused_output = torch.randn(2, 4, dtype=torch.bfloat16)
fused_residual = torch.randn(2, 4, dtype=torch.bfloat16)
def npu_add_rms_norm(
x: torch.Tensor,
residual: torch.Tensor,
gamma: torch.Tensor,
epsilon: float,
):
captured.update(x=x, residual=residual, gamma=gamma, epsilon=epsilon)
return fused_output, torch.empty(0), fused_residual
monkeypatch.setitem(
sys.modules,
"torch_npu",
types.SimpleNamespace(npu_add_rms_norm=npu_add_rms_norm),
)
norm = RMSNorm(4, eps=1e-5, dtype=torch.bfloat16)
x = torch.randn(2, 4, dtype=torch.bfloat16)
residual = torch.randn(2, 4, dtype=torch.bfloat16)
output, updated_residual = norm.forward_npu(x, residual)
assert output is fused_output
assert updated_residual is fused_residual
assert captured["x"] is x
assert captured["residual"] is residual
assert captured["gamma"] is norm.weight
assert captured["epsilon"] == 1e-5
# ── RMSNorm compile-path regression tests ──
+34
View File
@@ -0,0 +1,34 @@
# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
import pytest
import torch
from vllm_omni.diffusion.layers.norm import RMSNorm
from vllm_omni.platforms import current_omni_platform
pytestmark = [
pytest.mark.core_model,
pytest.mark.diffusion,
pytest.mark.cuda,
pytest.mark.skipif(not current_omni_platform.is_cuda(), reason="CUDA platform required"),
]
def test_rmsnorm_cuda_residual_matches_native_contract() -> None:
eps = 1e-6
device = torch.device(current_omni_platform.device_type)
torch.manual_seed(0)
norm = RMSNorm(64, eps=eps, dtype=torch.bfloat16).to(device)
x = torch.randn(2, 4, 64, device=device, dtype=torch.bfloat16)
residual = torch.randn_like(x)
x_before = x.clone()
residual_before = residual.clone()
expected_output, expected_residual = norm.forward_native(x_before, residual_before)
output, updated_residual = norm.forward_cuda(x, residual)
torch.testing.assert_close(updated_residual, expected_residual, atol=0, rtol=0)
torch.testing.assert_close(output, expected_output, atol=0, rtol=0)
torch.testing.assert_close(x, x_before, atol=0, rtol=0)
torch.testing.assert_close(residual, residual_before, atol=0, rtol=0)