[XPU] Use a fused GDN kernel from sgl-kernel for Qwen3.5 (#33354)
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
"""Qwen3.5-9B GSM8K accuracy on Intel XPU (TP=4).
|
||||
|
||||
Scored by ``simple_eval_gsm8k.GSM8KEval``.
|
||||
Scored by ``simple_eval_gsm8k.GSM8KEval``. Covers both the opt-in fused GDN
|
||||
SYCL kernel path (``--linear-attn-backend intel_xpu``) and the default Triton
|
||||
GDN path (``triton``, unchanged from other platforms).
|
||||
"""
|
||||
|
||||
import unittest
|
||||
@@ -18,9 +20,9 @@ register_xpu_ci(est_time=2400, suite="nightly-xpu-4-gpu", nightly=True)
|
||||
torch.xpu.is_available(),
|
||||
"Intel XPU not available (torch.xpu.is_available() returned False)",
|
||||
)
|
||||
class TestQwen3_5_9BXPU(SimpleEvalGSM8KXPUMixin, CustomTestCase):
|
||||
class Qwen3_5_9BXPUBase(SimpleEvalGSM8KXPUMixin, CustomTestCase):
|
||||
model = "Qwen/Qwen3.5-9B"
|
||||
tp_size = 4
|
||||
tp_size = 1
|
||||
accuracy = 0.90
|
||||
# max_tokens=8192 lets the GSM8K CoT complete under num_threads=4.
|
||||
num_examples = 50
|
||||
@@ -37,5 +39,23 @@ class TestQwen3_5_9BXPU(SimpleEvalGSM8KXPUMixin, CustomTestCase):
|
||||
]
|
||||
|
||||
|
||||
class TestQwen3_5_9BXPUDefault(Qwen3_5_9BXPUBase):
|
||||
"""Default path: Triton GDN kernels (unchanged from other platforms)."""
|
||||
|
||||
|
||||
class TestQwen3_5_9BXPUFusedGDN(Qwen3_5_9BXPUBase):
|
||||
"""Opt-in fused SYCL GDN kernel path (``--linear-attn-backend intel_xpu``).
|
||||
|
||||
Small ``num_examples`` since this is a smoke check of the fused-kernel
|
||||
dispatch, not a full accuracy regression test (already covered by the
|
||||
default Triton path above); accuracy threshold is left at 0 accordingly.
|
||||
"""
|
||||
|
||||
other_args = Qwen3_5_9BXPUBase.other_args + [
|
||||
"--linear-attn-backend",
|
||||
"intel_xpu",
|
||||
]
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
"""Intel XPU linear-attn (GDN) backend dispatch: intel_xpu is opt-in only
|
||||
(default stays triton, like every other platform) and fails fast rather than
|
||||
silently degrading when misconfigured. Pure dispatch-logic tests -- no XPU
|
||||
device required -- kept under test/registered/xpu to separate Intel-XPU-only
|
||||
behavior from the platform-agnostic linear-attn dispatch tests.
|
||||
"""
|
||||
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
from sglang.srt.layers.attention.linear import gdn_backend
|
||||
from sglang.srt.layers.attention.linear.gdn_backend import GDNKernelDispatcher
|
||||
from sglang.srt.layers.attention.linear.kda_backend import KDAKernelDispatcher
|
||||
from sglang.srt.layers.attention.linear.kernels.gdn_triton import TritonGDNKernel
|
||||
from sglang.srt.layers.attention.linear.utils import LinearAttnKernelBackend
|
||||
from sglang.srt.server_args import LINEAR_ATTN_KERNEL_BACKEND_CHOICES
|
||||
from sglang.test.ci.ci_register import register_xpu_ci
|
||||
from sglang.test.test_utils import CustomTestCase
|
||||
|
||||
register_xpu_ci(est_time=5, suite="stage-b-test-1-gpu-xpu")
|
||||
|
||||
|
||||
class TestIntelXpuGDNDispatch(CustomTestCase):
|
||||
def test_intel_xpu_is_a_registered_backend_choice(self):
|
||||
self.assertIn("intel_xpu", LINEAR_ATTN_KERNEL_BACKEND_CHOICES)
|
||||
|
||||
def test_intel_xpu_requires_xpu_hardware(self):
|
||||
with patch.object(gdn_backend, "is_xpu", return_value=False):
|
||||
with self.assertRaisesRegex(ValueError, "requires Intel XPU"):
|
||||
GDNKernelDispatcher(
|
||||
LinearAttnKernelBackend.INTEL_XPU,
|
||||
LinearAttnKernelBackend.TRITON,
|
||||
)
|
||||
with self.assertRaisesRegex(ValueError, "requires Intel XPU"):
|
||||
GDNKernelDispatcher(
|
||||
LinearAttnKernelBackend.TRITON,
|
||||
LinearAttnKernelBackend.INTEL_XPU,
|
||||
)
|
||||
|
||||
def test_intel_xpu_uses_triton_as_the_dispatcher_fallback_kernel(self):
|
||||
# The fused SYCL kernel is dispatched outside GDNKernelDispatcher (via
|
||||
# XpuGDNAttnBackend.forward_fused_gdn); the dispatcher itself only
|
||||
# needs a valid fallback kernel for requests that hook declines
|
||||
# (e.g. verify), which is Triton.
|
||||
with patch.object(gdn_backend, "is_xpu", return_value=True):
|
||||
dispatcher = GDNKernelDispatcher(
|
||||
LinearAttnKernelBackend.INTEL_XPU,
|
||||
LinearAttnKernelBackend.INTEL_XPU,
|
||||
)
|
||||
|
||||
self.assertIsInstance(dispatcher.decode_kernel, TritonGDNKernel)
|
||||
self.assertIsInstance(dispatcher.extend_kernel, TritonGDNKernel)
|
||||
self.assertIsInstance(dispatcher.verify_kernel, TritonGDNKernel)
|
||||
|
||||
|
||||
class TestIntelXpuKDADispatch(CustomTestCase):
|
||||
def test_intel_xpu_is_not_a_supported_kda_backend(self):
|
||||
# Unlike GDN, KDA has no Intel XPU SYCL kernel: intel_xpu must not be
|
||||
# silently treated as Triton, it should fail fast like any other
|
||||
# backend KDA does not implement.
|
||||
with self.assertRaisesRegex(ValueError, "Unsupported KDA decode backend"):
|
||||
KDAKernelDispatcher(
|
||||
decode_backend=LinearAttnKernelBackend.INTEL_XPU,
|
||||
prefill_backend=LinearAttnKernelBackend.TRITON,
|
||||
verify_backend=LinearAttnKernelBackend.TRITON,
|
||||
)
|
||||
with self.assertRaisesRegex(ValueError, "Unsupported KDA prefill backend"):
|
||||
KDAKernelDispatcher(
|
||||
decode_backend=LinearAttnKernelBackend.TRITON,
|
||||
prefill_backend=LinearAttnKernelBackend.INTEL_XPU,
|
||||
verify_backend=LinearAttnKernelBackend.TRITON,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user