94057c3d3e
PR Test (NPU) / check-changes (push) Has been cancelled
PR Test (NPU) / pr-gate (push) Has been cancelled
PR Test (NPU) / set-image-config (push) Has been cancelled
PR Test (NPU) / stage-b-test-1-npu-a2 (0) (push) Has been cancelled
PR Test (NPU) / stage-b-test-1-npu-a2 (1) (push) Has been cancelled
PR Test (NPU) / stage-b-test-2-npu-a2 (0) (push) Has been cancelled
PR Test (NPU) / stage-b-test-2-npu-a2 (1) (push) Has been cancelled
PR Test (NPU) / stage-b-test-4-npu-a3 (push) Has been cancelled
PR Test (NPU) / stage-b-test-16-npu-a3 (push) Has been cancelled
PR Test (NPU) / multimodal-gen-test-1-npu-a3 (push) Has been cancelled
PR Test (NPU) / multimodal-gen-test-2-npu-a3 (push) Has been cancelled
PR Test (Arm64) / pr-gate (push) Has been cancelled
PR Test (Arm64) / check-changes (push) Has been cancelled
PR Test (Arm64) / build-test (push) Has been cancelled
PR Test (sgl-router) / gate (push) Has been cancelled
PR Test (sgl-router) / tier-1 — lint (push) Has been cancelled
PR Test (sgl-router) / tier-2 — build + test (push) Has been cancelled
PR Test (sgl-router) / tier-3 — docker (placeholder) (push) Has been cancelled
PR Test (sgl-router) / tier-3 — k8s integration (push) Has been cancelled
PR Test (sgl-router) / tier-3 — e2e (push) Has been cancelled
PR Test (sgl-router) / finish (push) Has been cancelled
PR Test (NPU) / single-node-poc (map[name:qwen3_6_27b_w8a8_1p_in64k_out1k_50ms runner:linux-aarch64-a3-2 test_case:test/registered/ascend/performance/qwen3_6_27b/test_npu_qwen3_6_27b_w8a8_1p_in64k_out1k_50ms.py test_type:perf]) (push) Has been cancelled
PR Test (NPU) / pr-test-npu-finish (push) Has been cancelled
PR Test (Xeon) / pr-gate (push) Has been cancelled
PR Test (Xeon) / check-changes (push) Has been cancelled
PR Test (Xeon) / build-test (, xeon-gnr, base-b-test-cpu) (push) Has been cancelled
PR Test (XPU) / check-changes (push) Has been cancelled
PR Test (XPU) / pr-gate (push) Has been cancelled
PR Test (XPU) / stage-a-test-1-gpu-xpu (push) Has been cancelled
PR Test (XPU) / wait-for-stage-a (push) Has been cancelled
PR Test (XPU) / stage-b-test-1-gpu-xpu (push) Has been cancelled
PR Test (XPU) / finish (push) Has been cancelled
CI Model Inventory / build-inventory (push) Has been cancelled
Lint / lint (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark Compilation Check (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark - Manual Policy (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark - Request Processing (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark Summary (push) Has been cancelled
PR Test (SMG) / build-wheel (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on windows (x86_64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on macos (x86_64 - auto) (push) Has been cancelled
PR Test (SMG) / python-unit-tests (push) Has been cancelled
PR Test (SMG) / unit-tests (push) Has been cancelled
PR Test (SMG) / benchmarks (push) Has been cancelled
PR Test (SMG) / chat-completions (push) Has been cancelled
PR Test (SMG) / chat-completions-4gpu (push) Has been cancelled
PR Test (SMG) / e2e (push) Has been cancelled
PR Test (SMG) / docker-build-test (push) Has been cancelled
PR Test (SMG) / k8s-integration (push) Has been cancelled
PR Test (SMG) / finish (push) Has been cancelled
PR Test (SMG) / summarize-benchmarks (push) Has been cancelled
Release SGLang Model Gateway Docker Image / publish (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on macos (aarch64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (aarch64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (x86_64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (aarch64 - musllinux_1_1) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (x86_64 - musllinux_1_1) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / Build SDist (push) Has been cancelled
Release SGLang Model Gateway to PyPI / Upload to PyPI (push) Has been cancelled
Release SGLang Kernels / build-cu129-matrix (aarch64, 12.9, 3.10, arm-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / build-cu129-matrix (x86_64, 12.9, 3.10, x64-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / release-cu129 (push) Has been cancelled
Release SGLang Kernels / build-cu130-matrix (aarch64, 13.0, 3.10, arm-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / build-cu130-matrix (x86_64, 13.0, 3.10, x64-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / release-cu130 (push) Has been cancelled
Release SGLang Kernels / build-rocm-matrix (3.10, 700) (push) Has been cancelled
Release SGLang Kernels / build-rocm-matrix (3.10, 720) (push) Has been cancelled
Release SGLang Kernels / release-rocm700 (push) Has been cancelled
Release SGLang Kernels / release-rocm720 (push) Has been cancelled
Release SGLang Kernels / build-musa43 (43, 3.10) (push) Has been cancelled
Release SGLang Kernels / release-musa43 (push) Has been cancelled
171 lines
4.9 KiB
Python
171 lines
4.9 KiB
Python
"""Fused per-head Gemma-RMSNorm + partial NeoX RoPE for MiniMax-M3 attention.
|
|
|
|
In-place over a fused QKV tensor: normalizes + rotates one or more groups of
|
|
heads (each group = a contiguous head run sharing one norm weight, all getting
|
|
RoPE), leaving every other head (V, index-V) untouched. Consumes the model's
|
|
own ``cos_sin_cache`` (fp32) so the rotation matches sglang's RotaryEmbedding
|
|
exactly.
|
|
|
|
Two entry points:
|
|
|
|
* :func:`minimax_qknorm_rope` -- the original main-attention call
|
|
``(q | k | v ...)``: Q heads then K heads, both normed + roped.
|
|
* :func:`minimax_qknorm_rope_grouped` -- a multi-group launch (up to 4 groups),
|
|
used to fold the main Q/K *and* the sparse-index Q/K of one fused
|
|
qkv+index-qkv GEMM output into a single kernel launch (mirroring the
|
|
multi-branch single-launch design of ``fused_store_kv_index.cuh``).
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import TYPE_CHECKING, List, Sequence, Tuple
|
|
|
|
import torch
|
|
|
|
from sglang.jit_kernel.utils import (
|
|
cache_once,
|
|
is_arch_support_pdl,
|
|
load_jit,
|
|
make_cpp_args,
|
|
)
|
|
from sglang.srt.utils.custom_op import register_custom_op
|
|
|
|
if TYPE_CHECKING:
|
|
from tvm_ffi.module import Module
|
|
|
|
_MAX_GROUPS = 4
|
|
|
|
|
|
@cache_once
|
|
def _jit_module(pos_dtype, head_dim, rope_dim) -> Module:
|
|
args = make_cpp_args(pos_dtype, head_dim, rope_dim, is_arch_support_pdl())
|
|
return load_jit(
|
|
"fused_gemma_qknorm_rope",
|
|
*args,
|
|
cuda_files=["minimax/fused_gemma_qknorm_rope.cuh"],
|
|
cuda_wrappers=[("fused_gemma_qknorm_rope", f"fused_gemma_qknorm_rope<{args}>")],
|
|
)
|
|
|
|
|
|
@register_custom_op(mutates_args=["qkv"])
|
|
def _fused_gemma_qknorm_rope(
|
|
qkv: torch.Tensor,
|
|
w0: torch.Tensor,
|
|
w1: torch.Tensor,
|
|
w2: torch.Tensor,
|
|
w3: torch.Tensor,
|
|
cos_sin_cache: torch.Tensor,
|
|
positions: torch.Tensor,
|
|
off0: int,
|
|
cnt0: int,
|
|
off1: int,
|
|
cnt1: int,
|
|
off2: int,
|
|
cnt2: int,
|
|
off3: int,
|
|
cnt3: int,
|
|
num_groups: int,
|
|
eps: float,
|
|
) -> None:
|
|
# Wrap the tvm-ffi kernel as a custom op so torch.compile / piecewise CUDA
|
|
# graph can trace past the otherwise-opaque FFI call. The launch is
|
|
# graph-capturable (host-side constant offsets/counts), so it stays inside
|
|
# the captured region.
|
|
module = _jit_module(positions.dtype, 128, 64)
|
|
module.fused_gemma_qknorm_rope(
|
|
qkv,
|
|
w0,
|
|
w1,
|
|
w2,
|
|
w3,
|
|
cos_sin_cache,
|
|
positions,
|
|
off0,
|
|
cnt0,
|
|
off1,
|
|
cnt1,
|
|
off2,
|
|
cnt2,
|
|
off3,
|
|
cnt3,
|
|
num_groups,
|
|
eps,
|
|
)
|
|
|
|
|
|
def minimax_qknorm_rope_grouped(
|
|
qkv: torch.Tensor,
|
|
groups: Sequence[Tuple[torch.Tensor, int, int]],
|
|
cos_sin_cache: torch.Tensor,
|
|
positions: torch.Tensor,
|
|
eps: float,
|
|
) -> torch.Tensor:
|
|
"""Fused GemmaRMSNorm + partial NeoX RoPE over ``groups``, in place on ``qkv``.
|
|
|
|
``qkv`` is ``[T, total_heads * head_dim]`` (head_dim == 128). Each group is
|
|
``(weight, head_offset, head_count)``: ``head_count`` consecutive heads
|
|
starting at ``head_offset`` (in head units) are normed with ``weight``
|
|
(a ``[head_dim]`` bf16 tensor, the *raw* Gemma weight -- the kernel applies
|
|
``1 + weight``) and rotated. Heads outside every group are untouched.
|
|
|
|
Up to 4 groups are supported in one launch. The offsets/counts are
|
|
host-side constants, so the launch is CUDA-graph capturable.
|
|
"""
|
|
groups = [(w, off, cnt) for (w, off, cnt) in groups if cnt > 0]
|
|
num_groups = len(groups)
|
|
assert (
|
|
1 <= num_groups <= _MAX_GROUPS
|
|
), f"need 1..{_MAX_GROUPS} groups, got {num_groups}"
|
|
|
|
weights: List[torch.Tensor] = [g[0] for g in groups]
|
|
offsets: List[int] = [int(g[1]) for g in groups]
|
|
counts: List[int] = [int(g[2]) for g in groups]
|
|
# Pad weight slots up to 4 with a dummy (group 0's weight); the kernel never
|
|
# reads padded slots because num_groups bounds the in-kernel group scan.
|
|
while len(weights) < _MAX_GROUPS:
|
|
weights.append(weights[0])
|
|
offsets.append(0)
|
|
counts.append(0)
|
|
|
|
_fused_gemma_qknorm_rope(
|
|
qkv,
|
|
weights[0],
|
|
weights[1],
|
|
weights[2],
|
|
weights[3],
|
|
cos_sin_cache,
|
|
positions,
|
|
offsets[0],
|
|
counts[0],
|
|
offsets[1],
|
|
counts[1],
|
|
offsets[2],
|
|
counts[2],
|
|
offsets[3],
|
|
counts[3],
|
|
num_groups,
|
|
eps,
|
|
)
|
|
return qkv
|
|
|
|
|
|
def minimax_qknorm_rope(
|
|
qkv: torch.Tensor,
|
|
q_weight: torch.Tensor,
|
|
k_weight: torch.Tensor,
|
|
cos_sin_cache: torch.Tensor,
|
|
positions: torch.Tensor,
|
|
nq: int,
|
|
nk: int,
|
|
nv: int, # deprecated / ignored: V heads are simply left untouched
|
|
eps: float,
|
|
) -> torch.Tensor:
|
|
"""Main-attention layout ``[q (nq) | k (nk) | v ...]``: norm + rope Q then K."""
|
|
return minimax_qknorm_rope_grouped(
|
|
qkv,
|
|
[(q_weight, 0, nq), (k_weight, nq, nk)],
|
|
cos_sin_cache,
|
|
positions,
|
|
eps,
|
|
)
|