[MUSA][16/N] Add MUSA backend support for layers and DeepSeek models (V2/V3/R1) (#22774)

Co-authored-by: popsiclexu <zhenxue.xu@mthreads.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
This commit is contained in:
popsiclexu
2026-04-23 18:59:51 -07:00
committed by GitHub
co-authored by popsiclexu gemini-code-assist[bot]
parent cbc2bee547
commit b35213be11
27 changed files with 184 additions and 44 deletions
+1
View File
@@ -396,6 +396,7 @@ class Envs:
SGLANG_DG_CACHE_DIR = EnvStr(os.path.expanduser("~/.cache/deep_gemm")) SGLANG_DG_CACHE_DIR = EnvStr(os.path.expanduser("~/.cache/deep_gemm"))
SGLANG_DG_USE_NVRTC = EnvBool(False) SGLANG_DG_USE_NVRTC = EnvBool(False)
SGLANG_USE_DEEPGEMM_BMM = EnvBool(False) SGLANG_USE_DEEPGEMM_BMM = EnvBool(False)
SGLANG_DEEPGEMM_SANITY_CHECK = EnvBool(False)
# DeepSeek MHA Optimization # DeepSeek MHA Optimization
SGLANG_CHUNKED_PREFIX_CACHE_THRESHOLD = EnvInt(8192) SGLANG_CHUNKED_PREFIX_CACHE_THRESHOLD = EnvInt(8192)
+13
View File
@@ -36,6 +36,7 @@ from sglang.srt.utils import (
is_cpu, is_cpu,
is_cuda, is_cuda,
is_hip, is_hip,
is_musa,
is_npu, is_npu,
is_xpu, is_xpu,
set_weight_attrs, set_weight_attrs,
@@ -43,6 +44,7 @@ from sglang.srt.utils import (
from sglang.utils import resolve_obj_by_qualname from sglang.utils import resolve_obj_by_qualname
_is_cuda = is_cuda() _is_cuda = is_cuda()
_is_musa = is_musa()
_is_npu = is_npu() _is_npu = is_npu()
_is_cpu_amx_available = cpu_has_amx_support() _is_cpu_amx_available = cpu_has_amx_support()
_is_cpu = is_cpu() _is_cpu = is_cpu()
@@ -53,6 +55,8 @@ if _is_cuda or _is_xpu:
from sgl_kernel import gelu_and_mul, gelu_tanh_and_mul, silu_and_mul from sgl_kernel import gelu_and_mul, gelu_tanh_and_mul, silu_and_mul
elif _is_hip: elif _is_hip:
from sgl_kernel import gelu_and_mul, gelu_quick, gelu_tanh_and_mul, silu_and_mul from sgl_kernel import gelu_and_mul, gelu_quick, gelu_tanh_and_mul, silu_and_mul
elif _is_musa:
from sgl_kernel import silu_and_mul
if is_npu(): if is_npu():
import torch_npu import torch_npu
@@ -95,6 +99,15 @@ class SiluAndMul(MultiPlatformOp):
silu_and_mul(x, out) silu_and_mul(x, out)
return out return out
def forward_musa(self, x: torch.Tensor) -> torch.Tensor:
if not get_global_server_args().disable_piecewise_cuda_graph:
return self.forward_native(x)
if not hasattr(self, "_musa_swish_glu"):
# XXX (MUSA): nn.SwishGLU seems to have better performance than silu_and_mul on MUSA, we can switch to it for now. We can consider implementing a silu_and_mul kernel for MUSA in the future if needed.
self._musa_swish_glu = nn.SwishGLU()
return self._musa_swish_glu(x)
class GeluAndMul(MultiPlatformOp): class GeluAndMul(MultiPlatformOp):
def __init__(self, approximate="tanh"): def __init__(self, approximate="tanh"):
@@ -1,6 +1,6 @@
import logging import logging
import os import os
from contextlib import contextmanager from contextlib import contextmanager, nullcontext
from enum import IntEnum, auto from enum import IntEnum, auto
from typing import Dict, List, Tuple from typing import Dict, List, Tuple
@@ -14,10 +14,12 @@ from sglang.srt.distributed.device_communicators.pynccl_allocator import (
from sglang.srt.environ import envs from sglang.srt.environ import envs
from sglang.srt.layers.deep_gemm_wrapper.configurer import ENABLE_JIT_DEEPGEMM from sglang.srt.layers.deep_gemm_wrapper.configurer import ENABLE_JIT_DEEPGEMM
from sglang.srt.server_args import ServerArgs from sglang.srt.server_args import ServerArgs
from sglang.srt.utils import ceil_div, get_available_gpu_memory from sglang.srt.utils import ceil_div, get_available_gpu_memory, is_musa
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
_is_musa = is_musa()
if ENABLE_JIT_DEEPGEMM: if ENABLE_JIT_DEEPGEMM:
import deep_gemm import deep_gemm
@@ -332,9 +334,18 @@ class _BF16F32WarmupExecutor(_BaseWarmupExecutor):
deep_gemm.bf16_gemm_nt(self.lhs[:m], self.rhs, self.out[:m]) deep_gemm.bf16_gemm_nt(self.lhs[:m], self.rhs, self.out[:m])
@contextmanager
def deep_gemm_execution_hook( def deep_gemm_execution_hook(
m: int, n: int, k: int, num_groups: int, kernel_type: DeepGemmKernelType m: int, n: int, k: int, num_groups: int, kernel_type: DeepGemmKernelType
):
if _is_musa:
return nullcontext()
return _deep_gemm_execution_hook(m, n, k, num_groups, kernel_type)
@contextmanager
def _deep_gemm_execution_hook(
m: int, n: int, k: int, num_groups: int, kernel_type: DeepGemmKernelType
): ):
if m > 0: if m > 0:
_maybe_compile_deep_gemm_one_type_all(kernel_type, n, k, num_groups) _maybe_compile_deep_gemm_one_type_all(kernel_type, n, k, num_groups)
@@ -1,14 +1,22 @@
import logging import logging
from sglang.srt.environ import envs from sglang.srt.environ import envs
from sglang.srt.utils import get_device_sm, is_blackwell_supported from sglang.srt.utils import (
get_device_sm,
is_blackwell_supported,
is_cuda,
is_musa,
)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
_is_cuda = is_cuda()
_is_musa = is_musa()
def _compute_enable_deep_gemm(): def _compute_enable_deep_gemm():
sm_version = get_device_sm() sm_version = get_device_sm()
if sm_version < 90: if (_is_cuda and sm_version < 90) or (_is_musa and sm_version < 31):
return False return False
try: try:
@@ -23,3 +31,4 @@ ENABLE_JIT_DEEPGEMM = _compute_enable_deep_gemm()
DEEPGEMM_BLACKWELL = ENABLE_JIT_DEEPGEMM and is_blackwell_supported() DEEPGEMM_BLACKWELL = ENABLE_JIT_DEEPGEMM and is_blackwell_supported()
DEEPGEMM_SCALE_UE8M0 = DEEPGEMM_BLACKWELL DEEPGEMM_SCALE_UE8M0 = DEEPGEMM_BLACKWELL
DEEPGEMM_NEED_TMA_ALIGNED_SCALES = not (DEEPGEMM_SCALE_UE8M0 or _is_musa)
@@ -4,14 +4,15 @@ from typing import Any, Optional, Tuple
import torch import torch
from sglang.srt.environ import envs
from sglang.srt.layers.deep_gemm_wrapper import compile_utils from sglang.srt.layers.deep_gemm_wrapper import compile_utils
from sglang.srt.layers.deep_gemm_wrapper.configurer import ( # noqa: F401 from sglang.srt.layers.deep_gemm_wrapper.configurer import ( # noqa: F401
DEEPGEMM_BLACKWELL, DEEPGEMM_BLACKWELL,
DEEPGEMM_NEED_TMA_ALIGNED_SCALES,
DEEPGEMM_SCALE_UE8M0, DEEPGEMM_SCALE_UE8M0,
ENABLE_JIT_DEEPGEMM, ENABLE_JIT_DEEPGEMM,
) )
from sglang.srt.server_args import ServerArgs from sglang.srt.server_args import ServerArgs
from sglang.srt.utils import get_bool_env_var
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -19,7 +20,7 @@ if ENABLE_JIT_DEEPGEMM:
import deep_gemm import deep_gemm
from deep_gemm.utils.layout import get_mn_major_tma_aligned_tensor # noqa: F401 from deep_gemm.utils.layout import get_mn_major_tma_aligned_tensor # noqa: F401
_SANITY_CHECK = get_bool_env_var("SGLANG_DEEPGEMM_SANITY_CHECK") _SANITY_CHECK = envs.SGLANG_DEEPGEMM_SANITY_CHECK.get()
# TODO maybe rename these functions # TODO maybe rename these functions
+26 -1
View File
@@ -34,6 +34,7 @@ from sglang.srt.utils import (
is_cuda, is_cuda,
is_flashinfer_available, is_flashinfer_available,
is_hip, is_hip,
is_musa,
is_npu, is_npu,
is_xpu, is_xpu,
) )
@@ -41,6 +42,7 @@ from sglang.srt.utils import (
_is_cuda = is_cuda() _is_cuda = is_cuda()
_is_flashinfer_available = is_flashinfer_available() _is_flashinfer_available = is_flashinfer_available()
_is_hip = is_hip() _is_hip = is_hip()
_is_musa = is_musa()
_is_npu = is_npu() _is_npu = is_npu()
_use_aiter = get_bool_env_var("SGLANG_USE_AITER") and _is_hip _use_aiter = get_bool_env_var("SGLANG_USE_AITER") and _is_hip
_is_cpu_amx_available = cpu_has_amx_support() _is_cpu_amx_available = cpu_has_amx_support()
@@ -48,7 +50,7 @@ _is_cpu = is_cpu()
_is_xpu = is_xpu() _is_xpu = is_xpu()
_flashinfer_layernorm_available = False _flashinfer_layernorm_available = False
if _is_cuda or _is_xpu: if _is_cuda or _is_xpu or _is_musa:
if _is_flashinfer_available: if _is_flashinfer_available:
try: try:
from flashinfer.norm import layernorm from flashinfer.norm import layernorm
@@ -323,6 +325,29 @@ class RMSNorm(MultiPlatformOp):
rms_norm(out, x, self.weight.data, self.variance_epsilon) rms_norm(out, x, self.weight.data, self.variance_epsilon)
return out return out
def forward_musa(
self,
x: torch.Tensor,
residual: Optional[torch.Tensor] = None,
post_residual_addition: Optional[torch.Tensor] = None,
) -> Union[torch.Tensor, Tuple[torch.Tensor, torch.Tensor]]:
if not get_global_server_args().disable_piecewise_cuda_graph:
return self.forward_native(x, residual, post_residual_addition)
if not x.is_contiguous():
x = x.contiguous()
if residual is not None:
if post_residual_addition is not None:
residual = residual + post_residual_addition
fused_add_rmsnorm(x, residual, self.weight.data, self.variance_epsilon)
return x, residual
out = nn.functional.rms_norm(
x, (self.hidden_size,), self.weight.data, self.variance_epsilon
)
return out
def forward_native( def forward_native(
self, self,
x: torch.Tensor, x: torch.Tensor,
+11 -3
View File
@@ -3,12 +3,14 @@ import logging
import torch import torch
import triton import triton
from sglang.srt.utils import ceil_div, is_cuda from sglang.srt.utils import ceil_div, is_cuda, is_musa
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
_is_cuda = is_cuda() _is_cuda = is_cuda()
if _is_cuda: _is_musa = is_musa()
if _is_cuda or _is_musa:
from sglang.srt.layers.quantization.fp8_kernel import ( from sglang.srt.layers.quantization.fp8_kernel import (
sglang_per_token_group_quant_fp8 as per_token_group_quant_fp8, sglang_per_token_group_quant_fp8 as per_token_group_quant_fp8,
) )
@@ -665,6 +667,8 @@ def _fwd_kernel_ep_scatter_2(
HIDDEN_SIZE_PAD: tl.constexpr, HIDDEN_SIZE_PAD: tl.constexpr,
SCALE_HIDDEN_SIZE: tl.constexpr, SCALE_HIDDEN_SIZE: tl.constexpr,
SCALE_HIDDEN_SIZE_PAD: tl.constexpr, SCALE_HIDDEN_SIZE_PAD: tl.constexpr,
# Platform-specific semaphore for atomic_add performance tuning
ATOMIC_ADD_SEM: tl.constexpr,
): ):
start_token_id = tl.program_id(0) start_token_id = tl.program_id(0)
grid_num = tl.num_programs(0) grid_num = tl.num_programs(0)
@@ -689,7 +693,9 @@ def _fwd_kernel_ep_scatter_2(
topk_index = topk_idx_int32.to(tl.int64) topk_index = topk_idx_int32.to(tl.int64)
expert_id = tl.load(recv_topk + token_id * recv_topk_stride0 + topk_index) expert_id = tl.load(recv_topk + token_id * recv_topk_stride0 + topk_index)
if expert_id >= 0: if expert_id >= 0:
dest_token_index_int32 = tl.atomic_add(expert_start_loc + expert_id, 1) dest_token_index_int32 = tl.atomic_add(
expert_start_loc + expert_id, 1, sem=ATOMIC_ADD_SEM
)
dest_token_index = dest_token_index_int32.to(tl.int64) dest_token_index = dest_token_index_int32.to(tl.int64)
tl.store( tl.store(
@@ -783,6 +789,8 @@ def ep_scatter(
HIDDEN_SIZE_PAD=triton.next_power_of_2(hidden_size), HIDDEN_SIZE_PAD=triton.next_power_of_2(hidden_size),
SCALE_HIDDEN_SIZE=scale_hidden_size, SCALE_HIDDEN_SIZE=scale_hidden_size,
SCALE_HIDDEN_SIZE_PAD=triton.next_power_of_2(scale_hidden_size), SCALE_HIDDEN_SIZE_PAD=triton.next_power_of_2(scale_hidden_size),
# XXX (MUSA): Atomic add with "relaxed" semaphore on musa backend for better performance
ATOMIC_ADD_SEM=None if not _is_musa else "relaxed",
) )
return return
@@ -22,6 +22,7 @@ from sglang.srt.utils import (
get_bool_env_var, get_bool_env_var,
is_cuda, is_cuda,
is_hip, is_hip,
is_musa,
is_npu, is_npu,
) )
from sglang.srt.utils.offloader import get_offloader from sglang.srt.utils.offloader import get_offloader
@@ -42,6 +43,7 @@ _is_hip = is_hip()
_is_npu = is_npu() _is_npu = is_npu()
_is_cuda = is_cuda() _is_cuda = is_cuda()
_use_aiter = get_bool_env_var("SGLANG_USE_AITER") and _is_hip _use_aiter = get_bool_env_var("SGLANG_USE_AITER") and _is_hip
_is_musa = is_musa()
if not (_is_npu or _is_hip) and _is_cuda: if not (_is_npu or _is_hip) and _is_cuda:
from sgl_kernel import silu_and_mul from sgl_kernel import silu_and_mul
@@ -166,8 +168,9 @@ class DeepGemmRunnerCore(MoeRunnerCore):
device=hidden_states_device, device=hidden_states_device,
dtype=torch.bfloat16, dtype=torch.bfloat16,
) )
if not deep_gemm_wrapper.DEEPGEMM_SCALE_UE8M0: if deep_gemm_wrapper.DEEPGEMM_NEED_TMA_ALIGNED_SCALES:
hidden_states_scale = tma_align_input_scale(hidden_states_scale) hidden_states_scale = tma_align_input_scale(hidden_states_scale)
deep_gemm_wrapper.grouped_gemm_nt_f8f8bf16_contig( deep_gemm_wrapper.grouped_gemm_nt_f8f8bf16_contig(
(hidden_states, hidden_states_scale), (hidden_states, hidden_states_scale),
w13_weight_fp8, w13_weight_fp8,
@@ -203,7 +206,7 @@ class DeepGemmRunnerCore(MoeRunnerCore):
device=hidden_states_device, device=hidden_states_device,
dtype=torch.bfloat16, dtype=torch.bfloat16,
) )
if not deep_gemm_wrapper.DEEPGEMM_SCALE_UE8M0: if deep_gemm_wrapper.DEEPGEMM_NEED_TMA_ALIGNED_SCALES:
down_input_scale = tma_align_input_scale(down_input_scale) down_input_scale = tma_align_input_scale(down_input_scale)
deep_gemm_wrapper.grouped_gemm_nt_f8f8bf16_contig( deep_gemm_wrapper.grouped_gemm_nt_f8f8bf16_contig(
@@ -251,7 +254,7 @@ class DeepGemmRunnerCore(MoeRunnerCore):
hidden_states_scale = _cast_to_e8m0_with_rounding_up( hidden_states_scale = _cast_to_e8m0_with_rounding_up(
hidden_states_scale hidden_states_scale
) )
else: elif deep_gemm_wrapper.DEEPGEMM_NEED_TMA_ALIGNED_SCALES:
hidden_states_scale = deep_gemm_wrapper.get_mn_major_tma_aligned_tensor( hidden_states_scale = deep_gemm_wrapper.get_mn_major_tma_aligned_tensor(
hidden_states_scale hidden_states_scale
) )
@@ -317,7 +320,7 @@ class DeepGemmRunnerCore(MoeRunnerCore):
# GroupGemm-1 # GroupGemm-1
n = w2_weight.shape[1] n = w2_weight.shape[1]
if not deep_gemm_wrapper.DEEPGEMM_SCALE_UE8M0: if deep_gemm_wrapper.DEEPGEMM_NEED_TMA_ALIGNED_SCALES:
down_input_scale = deep_gemm_wrapper.get_mn_major_tma_aligned_tensor( down_input_scale = deep_gemm_wrapper.get_mn_major_tma_aligned_tensor(
down_input_scale down_input_scale
) )
@@ -20,6 +20,7 @@ from sglang.srt.utils import (
is_cpu, is_cpu,
is_cuda, is_cuda,
is_hip, is_hip,
is_musa,
is_xpu, is_xpu,
use_intel_xpu_backend, use_intel_xpu_backend,
) )
@@ -44,6 +45,7 @@ _is_cpu = is_cpu()
_use_aiter = get_bool_env_var("SGLANG_USE_AITER") and _is_hip _use_aiter = get_bool_env_var("SGLANG_USE_AITER") and _is_hip
_is_xpu = is_xpu() _is_xpu = is_xpu()
_use_sgl_xpu = use_intel_xpu_backend() _use_sgl_xpu = use_intel_xpu_backend()
_is_musa = is_musa()
if _is_cuda: if _is_cuda:
@@ -62,6 +64,10 @@ elif _is_hip:
# because the code uses moe_sum_reduce_triton as fallback (line 619) # because the code uses moe_sum_reduce_triton as fallback (line 619)
elif _is_xpu: elif _is_xpu:
from sgl_kernel import moe_sum_reduce, silu_and_mul from sgl_kernel import moe_sum_reduce, silu_and_mul
elif _is_musa:
from sgl_kernel import moe_sum_reduce
_silu_and_mul_musa = torch.nn.SwishGLU()
# Try to import vllm_ops for non-CUDA/HIP/XPU platforms # Try to import vllm_ops for non-CUDA/HIP/XPU platforms
_has_vllm_ops = False _has_vllm_ops = False
@@ -534,6 +540,8 @@ def _fused_moe_kernel_sequence(
down_moe_use_tma, down_moe_use_tma,
activation, activation,
) )
elif _is_musa:
intermediate_cache2 = _silu_and_mul_musa(intermediate_cache1.view(-1, N))
else: else:
if _has_vllm_ops: if _has_vllm_ops:
vllm_ops.silu_and_mul( vllm_ops.silu_and_mul(
@@ -647,7 +655,7 @@ def _fused_moe_kernel_sequence(
if no_combine: if no_combine:
pass pass
elif _is_cuda: elif _is_cuda or _is_musa:
if use_fused_moe_sum_all_reduce: if use_fused_moe_sum_all_reduce:
if routed_scaling_factor != 1.0: if routed_scaling_factor != 1.0:
assert out_slice is not None assert out_slice is not None
@@ -5,13 +5,14 @@ from typing import Tuple
import torch import torch
import triton import triton
from sglang.srt.utils import is_cuda, is_hip, is_xpu from sglang.srt.utils import is_cuda, is_hip, is_musa, is_xpu
_is_cuda = is_cuda() _is_cuda = is_cuda()
_is_hip = is_hip() _is_hip = is_hip()
_is_xpu = is_xpu() _is_xpu = is_xpu()
_is_musa = is_musa()
if _is_cuda or _is_hip or _is_xpu: if _is_cuda or _is_hip or _is_xpu or _is_musa:
from sgl_kernel import moe_align_block_size as sgl_moe_align_block_size from sgl_kernel import moe_align_block_size as sgl_moe_align_block_size
+9 -7
View File
@@ -62,6 +62,7 @@ from sglang.srt.utils import (
is_cpu, is_cpu,
is_cuda, is_cuda,
is_hip, is_hip,
is_musa,
is_npu, is_npu,
is_xpu, is_xpu,
) )
@@ -80,8 +81,9 @@ _is_xpu = is_xpu()
_is_npu = is_npu() _is_npu = is_npu()
_is_xpu = is_xpu() _is_xpu = is_xpu()
_use_aiter = get_bool_env_var("SGLANG_USE_AITER") and _is_hip _use_aiter = get_bool_env_var("SGLANG_USE_AITER") and _is_hip
_is_musa = is_musa()
if _is_cuda: if _is_cuda or _is_musa:
from sgl_kernel import moe_fused_gate from sgl_kernel import moe_fused_gate
try: try:
@@ -124,7 +126,7 @@ if _is_cuda:
except ImportError as e: except ImportError as e:
pass pass
if _is_cuda or _is_hip or _is_xpu: if _is_cuda or _is_hip or _is_xpu or _is_musa:
from sgl_kernel import topk_softmax from sgl_kernel import topk_softmax
try: try:
@@ -851,7 +853,7 @@ def biased_grouped_topk_gpu(
return topk_weights, topk_ids return topk_weights, topk_ids
elif ( elif (
_is_cuda (_is_cuda or _is_musa)
# moe_fused_gate kernel ensures that num_experts/num_expert_group does not exceed MAX_VPT=32 now. And when kernel can handle MAX_VPT > 32, we can remove this assertion. # moe_fused_gate kernel ensures that num_experts/num_expert_group does not exceed MAX_VPT=32 now. And when kernel can handle MAX_VPT > 32, we can remove this assertion.
and experts_per_group <= 32 and experts_per_group <= 32
and is_power_of_two(num_experts) and is_power_of_two(num_experts)
@@ -1077,7 +1079,6 @@ def select_experts(
num_token_non_padded: Optional[torch.Tensor] = None, num_token_non_padded: Optional[torch.Tensor] = None,
expert_location_dispatch_info: Optional[ExpertLocationDispatchInfo] = None, expert_location_dispatch_info: Optional[ExpertLocationDispatchInfo] = None,
) -> StandardTopKOutput: ) -> StandardTopKOutput:
top_k = topk_config.top_k top_k = topk_config.top_k
use_grouped_topk = topk_config.use_grouped_topk use_grouped_topk = topk_config.use_grouped_topk
topk_group = topk_config.topk_group topk_group = topk_config.topk_group
@@ -1094,13 +1095,14 @@ def select_experts(
scoring_func = topk_config.scoring_func scoring_func = topk_config.scoring_func
router_logits, correction_bias = ( (
expert_location_dispatch.transform_select_experts_inputs( router_logits,
correction_bias,
) = expert_location_dispatch.transform_select_experts_inputs(
router_logits=router_logits, router_logits=router_logits,
correction_bias=correction_bias, correction_bias=correction_bias,
info=expert_location_dispatch_info, info=expert_location_dispatch_info,
) )
)
# DeepSeek V2/V3/R1 series models use grouped_top_k # DeepSeek V2/V3/R1 series models use grouped_top_k
# remove num_fused_shared_experts from grouped_topk/biased_grouped_topk # remove num_fused_shared_experts from grouped_topk/biased_grouped_topk
@@ -85,6 +85,7 @@ from sglang.srt.utils import (
is_cpu, is_cpu,
is_cuda, is_cuda,
is_hip, is_hip,
is_musa,
is_npu, is_npu,
is_sm90_supported, is_sm90_supported,
is_sm100_supported, is_sm100_supported,
@@ -103,6 +104,7 @@ if TYPE_CHECKING:
_is_hip = is_hip() _is_hip = is_hip()
_is_cuda = is_cuda() _is_cuda = is_cuda()
_is_musa = is_musa()
_is_npu = is_npu() _is_npu = is_npu()
_is_cpu_amx_available = cpu_has_amx_support() _is_cpu_amx_available = cpu_has_amx_support()
_is_cpu = is_cpu() _is_cpu = is_cpu()
@@ -185,6 +187,9 @@ class Fp8Config(QuantizationConfig):
return [torch.bfloat16, torch.half] return [torch.bfloat16, torch.half]
def get_min_capability(self) -> int: def get_min_capability(self) -> int:
if _is_musa:
return 31
return 100 if self.use_mxfp8 else 80 return 100 if self.use_mxfp8 else 80
@classmethod @classmethod
@@ -37,6 +37,7 @@ from sglang.srt.utils import (
is_cpu, is_cpu,
is_cuda, is_cuda,
is_hip, is_hip,
is_musa,
is_sm100_supported, is_sm100_supported,
is_sm120_supported, is_sm120_supported,
log_info_on_rank0, log_info_on_rank0,
@@ -47,11 +48,12 @@ from sglang.srt.utils.patch_torch import register_fake_if_exists
_is_hip = is_hip() _is_hip = is_hip()
_is_cuda = is_cuda() _is_cuda = is_cuda()
_is_cpu = is_cpu() _is_cpu = is_cpu()
_is_musa = is_musa()
_is_sm100_supported = is_sm100_supported() _is_sm100_supported = is_sm100_supported()
_is_sm120_supported = is_sm120_supported() _is_sm120_supported = is_sm120_supported()
_use_aiter = get_bool_env_var("SGLANG_USE_AITER") and _is_hip _use_aiter = get_bool_env_var("SGLANG_USE_AITER") and _is_hip
if _is_cuda: if _is_cuda or _is_musa:
from sgl_kernel import sgl_per_token_quant_fp8 from sgl_kernel import sgl_per_token_quant_fp8
from sglang.jit_kernel.per_tensor_quant_fp8 import ( from sglang.jit_kernel.per_tensor_quant_fp8 import (
@@ -506,7 +508,7 @@ def sglang_per_token_group_quant_fp8(
# Enable v2 kernel by default on supported group sizes # Enable v2 kernel by default on supported group sizes
_V2_KERNEL_SUPPORTED_GROUP_SIZES = [16, 32, 64, 128] _V2_KERNEL_SUPPORTED_GROUP_SIZES = [16, 32, 64, 128]
if enable_v2 is None: if enable_v2 is None:
enable_v2 = group_size in _V2_KERNEL_SUPPORTED_GROUP_SIZES enable_v2 = group_size in _V2_KERNEL_SUPPORTED_GROUP_SIZES or _is_musa
if x.shape[0] > 0: if x.shape[0] > 0:
# Temporary # Temporary
@@ -1111,6 +1113,11 @@ def w8a8_block_fp8_matmul_deepgemm(
# Deepgemm only supports output tensor type as bfloat16 # Deepgemm only supports output tensor type as bfloat16
assert C.dtype == torch.bfloat16 and deep_gemm_wrapper.ENABLE_JIT_DEEPGEMM assert C.dtype == torch.bfloat16 and deep_gemm_wrapper.ENABLE_JIT_DEEPGEMM
if _is_musa:
# XXX (MUSA): `deep_gemm_fp8_fp8_bf16_nt` on MUSA requires contiguous tensors
As = As.contiguous()
Bs = Bs.contiguous()
deep_gemm_fp8_fp8_bf16_nt(A, As, B, Bs, C) deep_gemm_fp8_fp8_bf16_nt(A, As, B, Bs, C)
return C return C
@@ -39,6 +39,7 @@ from sglang.srt.utils import (
is_flashinfer_available, is_flashinfer_available,
is_gfx95_supported, is_gfx95_supported,
is_hip, is_hip,
is_musa,
is_sm90_supported, is_sm90_supported,
is_sm100_supported, is_sm100_supported,
is_sm120_supported, is_sm120_supported,
@@ -54,6 +55,7 @@ _is_fp8_fnuz = is_fp8_fnuz()
_is_sm100_supported = is_sm100_supported() _is_sm100_supported = is_sm100_supported()
_is_sm120_supported = is_sm120_supported() _is_sm120_supported = is_sm120_supported()
_is_gfx95_supported = is_gfx95_supported() _is_gfx95_supported = is_gfx95_supported()
_is_musa = is_musa()
_use_aiter = get_bool_env_var("SGLANG_USE_AITER") and _is_hip _use_aiter = get_bool_env_var("SGLANG_USE_AITER") and _is_hip
_use_aiter_gfx95 = _use_aiter and _is_gfx95_supported _use_aiter_gfx95 = _use_aiter and _is_gfx95_supported
@@ -695,4 +695,7 @@ class UnquantizedFusedMoEMethod(FusedMoEMethodBase, MultiPlatformOp):
def forward_tpu(self, *args, **kwargs) -> CombineInput: def forward_tpu(self, *args, **kwargs) -> CombineInput:
raise NotImplementedError("The TPU backend currently does not support MoE.") raise NotImplementedError("The TPU backend currently does not support MoE.")
def forward_musa(self, *args, **kwargs) -> CombineInput:
return self.forward_cuda(*args, **kwargs)
forward_native = forward_cpu forward_native = forward_cpu
+7 -1
View File
@@ -16,7 +16,12 @@ from sglang.srt.layers.utils.logprob import get_token_ids_logprobs, get_top_logp
from sglang.srt.sampling.sampling_batch_info import SamplingBatchInfo from sglang.srt.sampling.sampling_batch_info import SamplingBatchInfo
from sglang.srt.sampling.sampling_params import TOP_K_ALL from sglang.srt.sampling.sampling_params import TOP_K_ALL
from sglang.srt.server_args import get_global_server_args from sglang.srt.server_args import get_global_server_args
from sglang.srt.utils.common import crash_on_warnings, get_bool_env_var, is_cuda, is_npu from sglang.srt.utils.common import (
crash_on_warnings,
get_bool_env_var,
is_cuda,
is_npu,
)
if is_cuda(): if is_cuda():
from flashinfer.sampling import ( from flashinfer.sampling import (
@@ -27,6 +32,7 @@ if is_cuda():
top_k_renorm_prob, top_k_renorm_prob,
top_p_renorm_prob, top_p_renorm_prob,
) )
if is_npu(): if is_npu():
import torch_npu import torch_npu
@@ -13,6 +13,7 @@ from sglang.srt.model_executor.forward_batch_info import ForwardBatch
from sglang.srt.models.deepseek_common.utils import ( from sglang.srt.models.deepseek_common.utils import (
_is_cuda, _is_cuda,
_is_hip, _is_hip,
_is_musa,
_is_npu, _is_npu,
_use_aiter_gfx95, _use_aiter_gfx95,
) )
@@ -491,7 +492,7 @@ class DeepseekMHAForwardMixin:
# Temporary for DeepSeek V3/R1 only, but can generalize if needed # Temporary for DeepSeek V3/R1 only, but can generalize if needed
k_shape = (k_nope.shape[0], self.num_local_heads, self.qk_head_dim) k_shape = (k_nope.shape[0], self.num_local_heads, self.qk_head_dim)
if ( if (
_is_cuda (_is_cuda or _is_musa)
and (self.num_local_heads == 128) and (self.num_local_heads == 128)
and (self.qk_nope_head_dim == 128) and (self.qk_nope_head_dim == 128)
and (self.qk_rope_head_dim == 64) and (self.qk_rope_head_dim == 64)
@@ -21,6 +21,7 @@ from sglang.srt.models.deepseek_common.utils import (
_is_cuda, _is_cuda,
_is_gfx95_supported, _is_gfx95_supported,
_is_hip, _is_hip,
_is_musa,
_use_aiter, _use_aiter,
_use_aiter_gfx95, _use_aiter_gfx95,
) )
@@ -553,6 +554,11 @@ class DeepseekMLAForwardMixin:
torch.bfloat16, torch.bfloat16,
) )
attn_bmm_output = attn_bmm_output.transpose(0, 1).flatten(1, 2) attn_bmm_output = attn_bmm_output.transpose(0, 1).flatten(1, 2)
elif _is_musa:
attn_bmm_output = torch.bmm(
attn_output.to(torch.bfloat16).transpose(0, 1), self.w_vc
)
attn_bmm_output = attn_bmm_output.transpose(0, 1).flatten(1, 2)
else: else:
if is_in_piecewise_cuda_graph(): if is_in_piecewise_cuda_graph():
# torch dynamo requires out= op was called where output tensor was non-contiguous # torch dynamo requires out= op was called where output tensor was non-contiguous
@@ -49,6 +49,7 @@ from sglang.srt.models.deepseek_common.utils import (
_is_cuda, _is_cuda,
_is_fp8_fnuz, _is_fp8_fnuz,
_is_hip, _is_hip,
_is_musa,
_is_npu, _is_npu,
_is_xpu, _is_xpu,
_use_aiter_gfx95, _use_aiter_gfx95,
@@ -498,7 +499,7 @@ class DeepseekV2WeightLoaderMixin:
) )
if ( if (
(_is_cuda or _is_xpu) (_is_cuda or _is_musa or _is_xpu)
and weight_block_size[0] == 128 and weight_block_size[0] == 128
and weight_block_size[1] == 128 and weight_block_size[1] == 128
): ):
@@ -585,6 +586,14 @@ class DeepseekV2WeightLoaderMixin:
) )
if _is_hip: if _is_hip:
self_attn.w_scale *= 2.0 self_attn.w_scale *= 2.0
# XXX (MUSA): Remove this after adding FP8 support in bmm kernel on MUSA
if _is_musa and w.dtype == torch.float8_e4m3fn:
self_attn.w_kc = (
self_attn.w_kc.to(torch.bfloat16) * self_attn.w_scale
)
self_attn.w_vc = (
self_attn.w_vc.to(torch.bfloat16) * self_attn.w_scale
)
else: else:
num_tiles_k = self_attn.qk_nope_head_dim // weight_block_size[1] num_tiles_k = self_attn.qk_nope_head_dim // weight_block_size[1]
num_tiles_n = self_attn.v_head_dim // weight_block_size[0] num_tiles_n = self_attn.v_head_dim // weight_block_size[0]
@@ -29,6 +29,7 @@ from sglang.srt.utils import (
is_cuda, is_cuda,
is_gfx95_supported, is_gfx95_supported,
is_hip, is_hip,
is_musa,
is_npu, is_npu,
is_nvidia_cublas_version_ge_12_9, is_nvidia_cublas_version_ge_12_9,
is_xpu, is_xpu,
@@ -37,6 +38,7 @@ from sglang.srt.utils import (
_is_hip = is_hip() _is_hip = is_hip()
_is_cuda = is_cuda() _is_cuda = is_cuda()
_is_npu = is_npu() _is_npu = is_npu()
_is_musa = is_musa()
_is_fp8_fnuz = is_fp8_fnuz() _is_fp8_fnuz = is_fp8_fnuz()
_use_aiter = get_bool_env_var("SGLANG_USE_AITER") and _is_hip _use_aiter = get_bool_env_var("SGLANG_USE_AITER") and _is_hip
_is_cpu_amx_available = cpu_has_amx_support() _is_cpu_amx_available = cpu_has_amx_support()
+13 -4
View File
@@ -141,6 +141,7 @@ from sglang.srt.models.deepseek_common.utils import (
_is_cuda, _is_cuda,
_is_gfx95_supported, _is_gfx95_supported,
_is_hip, _is_hip,
_is_musa,
_is_npu, _is_npu,
_is_xpu, _is_xpu,
_use_aiter, _use_aiter,
@@ -182,6 +183,8 @@ elif _is_npu:
forward_mla_core_npu, forward_mla_core_npu,
forward_mla_prepare_npu, forward_mla_prepare_npu,
) )
elif _is_musa:
from sgl_kernel import dsv3_fused_a_gemm, dsv3_router_gemm
else: else:
pass pass
@@ -640,7 +643,9 @@ class DeepseekV2MoE(nn.Module):
expert_location_dispatch_info=dispatch_info, expert_location_dispatch_info=dispatch_info,
) )
final_hidden_states = self.experts(hidden_states, topk_output) final_hidden_states = self.experts(hidden_states, topk_output)
if not _is_cuda or isinstance(self.experts.quant_method, KTEPWrapperMethod): if not (_is_cuda or _is_musa) or isinstance(
self.experts.quant_method, KTEPWrapperMethod
):
final_hidden_states *= self.routed_scaling_factor final_hidden_states *= self.routed_scaling_factor
current_stream.wait_stream(self.alt_stream) current_stream.wait_stream(self.alt_stream)
@@ -725,6 +730,7 @@ class DeepseekV2MoE(nn.Module):
) )
if ( if (
not _is_cuda not _is_cuda
and not _is_musa
and not _is_xpu and not _is_xpu
and not _use_aiter and not _use_aiter
or isinstance(self.experts.quant_method, KTEPWrapperMethod) or isinstance(self.experts.quant_method, KTEPWrapperMethod)
@@ -1910,7 +1916,7 @@ class DeepseekV2Model(nn.Module):
self.alt_stream = ( self.alt_stream = (
torch.cuda.Stream() torch.cuda.Stream()
if _is_cuda or envs.SGLANG_NPU_USE_MULTI_STREAM.get() if _is_cuda or _is_musa or envs.SGLANG_NPU_USE_MULTI_STREAM.get()
else None else None
) )
@@ -2249,12 +2255,15 @@ class DeepseekV2ForCausalLM(nn.Module, DeepseekV2WeightLoaderMixin):
or self.config.n_shared_experts != 1 or self.config.n_shared_experts != 1
): ):
disable_reason = "Config does not support fused shared expert(s)." disable_reason = "Config does not support fused shared expert(s)."
elif (not _is_cuda or torch.cuda.get_device_capability("cuda") < (8, 0)) and ( elif (
not _is_hip or torch.cuda.get_device_capability("cuda") < (9, 4) (not _is_cuda or torch.cuda.get_device_capability("cuda") < (8, 0))
and (not _is_hip or torch.cuda.get_device_capability("cuda") < (9, 4))
and (not _is_musa or torch.musa.get_device_capability("musa") < (3, 1))
): ):
disable_reason = ( disable_reason = (
"Only Deepseek V3/R1 on NV-platform with capability >= 80 " "Only Deepseek V3/R1 on NV-platform with capability >= 80 "
"or AMD-platform with capability >= gfx942(MI30x) can use shared experts fusion optimization." "or AMD-platform with capability >= gfx942(MI30x) can use shared experts fusion optimization."
"or MT-platform with capability >= 31 can use shared experts fusion optimization."
) )
elif get_moe_expert_parallel_world_size() > 1 and ( elif get_moe_expert_parallel_world_size() > 1 and (
not _is_hip or torch.cuda.get_device_capability("cuda") < (9, 4) not _is_hip or torch.cuda.get_device_capability("cuda") < (9, 4)
@@ -376,6 +376,7 @@ class SchedulerMetricsMixin:
{ {
"cpu": "cpu graph", "cpu": "cpu graph",
"npu": "npu graph", "npu": "npu graph",
"musa": "musa graph",
}, },
) )
@@ -561,6 +562,7 @@ class SchedulerMetricsMixin:
{ {
"cpu": "cpu graph", "cpu": "cpu graph",
"npu": "npu graph", "npu": "npu graph",
"musa": "musa graph",
}, },
) )
msg += ( msg += (
+1 -1
View File
@@ -4506,7 +4506,7 @@ class ServerArgs:
"--device", "--device",
type=str, type=str,
default=ServerArgs.device, default=ServerArgs.device,
help="The device to use ('cuda', 'xpu', 'hpu', 'npu', 'cpu'). Defaults to auto-detection if not specified.", help="The device to use ('cuda', 'xpu', 'hpu', 'npu', 'cpu', 'musa'). Defaults to auto-detection if not specified.",
) )
parser.add_argument( parser.add_argument(
"--tensor-parallel-size", "--tensor-parallel-size",
+4 -3
View File
@@ -4,13 +4,14 @@ from typing import List, Optional
import torch import torch
from sglang.srt.utils import is_cuda, is_hip, is_npu from sglang.srt.utils import is_cuda, is_hip, is_musa, is_npu
_is_cuda = is_cuda() _is_cuda = is_cuda()
_is_hip = is_hip() _is_hip = is_hip()
_is_npu = is_npu() _is_npu = is_npu()
_is_musa = is_musa()
if _is_cuda or _is_hip: if _is_cuda or _is_hip or _is_musa:
from sgl_kernel import ( from sgl_kernel import (
build_tree_kernel_efficient as sgl_build_tree_kernel_efficient, build_tree_kernel_efficient as sgl_build_tree_kernel_efficient,
) )
@@ -169,7 +170,7 @@ def verify_tree_greedy_func(
target_predict: torch.Tensor, target_predict: torch.Tensor,
topk: int = -1, topk: int = -1,
): ):
if _is_cuda or _is_hip: if _is_cuda or _is_hip or _is_musa:
from sgl_kernel import verify_tree_greedy from sgl_kernel import verify_tree_greedy
verify_tree_greedy( verify_tree_greedy(
@@ -71,12 +71,14 @@ from sglang.srt.utils import (
empty_context, empty_context,
get_available_gpu_memory, get_available_gpu_memory,
is_cuda, is_cuda,
is_musa,
is_npu, is_npu,
next_power_of_2, next_power_of_2,
) )
from sglang.srt.utils.patch_torch import monkey_patch_torch_reductions from sglang.srt.utils.patch_torch import monkey_patch_torch_reductions
_is_npu = is_npu() _is_npu = is_npu()
_is_musa = is_musa()
if is_cuda(): if is_cuda():
from sgl_kernel import segment_packbits # noqa: F401 from sgl_kernel import segment_packbits # noqa: F401
@@ -1214,7 +1216,7 @@ class EAGLEWorker(TpModelWorker):
return success, message return success, message
@torch.compile(dynamic=True, disable=_is_npu) @torch.compile(dynamic=True, disable=(_is_npu or _is_musa))
def get_last_loc_large_page_size_top_k_1( def get_last_loc_large_page_size_top_k_1(
req_to_token: torch.Tensor, req_to_token: torch.Tensor,
req_pool_indices: torch.Tensor, req_pool_indices: torch.Tensor,
+2 -1
View File
@@ -177,7 +177,8 @@ def assign_draft_cache_locs(
mask = copy_offset < copy_len mask = copy_offset < copy_len
data = tl.load(out_cache_ptr + copy_offset, mask=mask) data = tl.load(out_cache_ptr + copy_offset, mask=mask)
tl.store(token_pool + kv_start + copy_offset, data, mask=mask) tl.store(token_pool + kv_start + copy_offset, data, mask=mask)
if page_size != 1 and topk != 1 and duplicate_cache_len > 0: # XXX (MUSA): Triton issue: chained boolean operators (A or B or C) are not supported.
if (page_size != 1 and topk != 1) and duplicate_cache_len > 0:
# Part 2: Copy indices into source_cache_loc and target_cache_loc # Part 2: Copy indices into source_cache_loc and target_cache_loc
# Expected output: src:[8,9,10,8,9,10...] tgt:[16,17,18,24,25,26...] # Expected output: src:[8,9,10,8,9,10...] tgt:[16,17,18,24,25,26...]
prefix_len = tl.load(seq_lens + pid) prefix_len = tl.load(seq_lens + pid)
+3 -1
View File
@@ -1530,7 +1530,7 @@ def get_amdgpu_memory_capacity():
def get_device_sm(): def get_device_sm():
if torch.cuda.is_available(): if torch.cuda.is_available() or is_musa():
major, minor = torch.cuda.get_device_capability() major, minor = torch.cuda.get_device_capability()
return major * 10 + minor return major * 10 + minor
return 0 return 0
@@ -2074,6 +2074,8 @@ def direct_register_custom_op(
my_lib.impl(op_name, op_func, "PrivateUse1") my_lib.impl(op_name, op_func, "PrivateUse1")
elif is_xpu(): elif is_xpu():
my_lib.impl(op_name, op_func, "XPU") my_lib.impl(op_name, op_func, "XPU")
elif is_musa():
my_lib.impl(op_name, op_func, "MUSA")
else: else:
my_lib.impl(op_name, op_func, "CUDA") my_lib.impl(op_name, op_func, "CUDA")
if fake_impl is not None: if fake_impl is not None: