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
387 lines
11 KiB
Python
387 lines
11 KiB
Python
from __future__ import annotations
|
|
|
|
import torch
|
|
import triton
|
|
import triton.language as tl
|
|
|
|
from sglang.jit_kernel.utils import is_arch_support_pdl
|
|
from sglang.srt.runtime_context import get_parallel
|
|
|
|
|
|
@triton.jit
|
|
def set_mla_kv_buffer_kernel(
|
|
kv_buffer_ptr,
|
|
cache_k_nope_ptr,
|
|
cache_k_rope_ptr,
|
|
loc_ptr,
|
|
buffer_stride: tl.constexpr,
|
|
nope_stride: tl.constexpr,
|
|
rope_stride: tl.constexpr,
|
|
nope_dim: tl.constexpr,
|
|
rope_dim: tl.constexpr,
|
|
BLOCK: tl.constexpr,
|
|
DCP_RANK: tl.constexpr,
|
|
DCP_WORLD_SIZE: tl.constexpr,
|
|
USE_GDC: tl.constexpr = False,
|
|
):
|
|
pid_loc = tl.program_id(0)
|
|
pid_blk = tl.program_id(1)
|
|
|
|
base = pid_blk * BLOCK
|
|
offs = base + tl.arange(0, BLOCK)
|
|
total_dim = nope_dim + rope_dim
|
|
mask = offs < total_dim
|
|
|
|
if USE_GDC:
|
|
tl.extra.cuda.gdc_wait()
|
|
|
|
loc = tl.load(loc_ptr + pid_loc).to(tl.int64)
|
|
is_valid = loc % DCP_WORLD_SIZE == DCP_RANK
|
|
safe_loc = tl.where(is_valid, loc, 0)
|
|
safe_loc = safe_loc // DCP_WORLD_SIZE
|
|
dst_ptr = kv_buffer_ptr + safe_loc * buffer_stride + offs
|
|
|
|
# Three-way branch to handle boundary correctly while preserving fast path
|
|
if base + BLOCK <= nope_dim:
|
|
# Fast path: entire block is in nope region
|
|
src = tl.load(
|
|
cache_k_nope_ptr + pid_loc * nope_stride + offs,
|
|
mask=mask,
|
|
)
|
|
elif base >= nope_dim:
|
|
# Fast path: entire block is in rope region
|
|
offs_rope = offs - nope_dim
|
|
src = tl.load(
|
|
cache_k_rope_ptr + pid_loc * rope_stride + offs_rope,
|
|
mask=mask,
|
|
)
|
|
else:
|
|
# Boundary case: block spans nope/rope boundary (e.g., FP8 with nope_dim=528)
|
|
# Handle each offset individually to avoid negative indexing
|
|
is_nope = offs < nope_dim
|
|
is_rope = (offs >= nope_dim) & (offs < (nope_dim + rope_dim))
|
|
|
|
src_nope = tl.load(
|
|
cache_k_nope_ptr + pid_loc * nope_stride + offs,
|
|
mask=mask & is_nope,
|
|
other=0,
|
|
)
|
|
src_rope = tl.load(
|
|
cache_k_rope_ptr + pid_loc * rope_stride + (offs - nope_dim),
|
|
mask=mask & is_rope,
|
|
other=0,
|
|
)
|
|
|
|
src = tl.where(is_nope, src_nope, src_rope)
|
|
|
|
tl.store(dst_ptr, src, mask=mask & is_valid)
|
|
|
|
if USE_GDC:
|
|
tl.extra.cuda.gdc_launch_dependents()
|
|
|
|
|
|
# Above this loc count the TMA bulk-store path overtakes the single-CTA-per-loc
|
|
# Triton kernel. Below it, Triton with BLOCK = next_pow2(total_dim) (one CTA
|
|
# does the whole row in one tile, no boundary fan-out) is the winning fallback.
|
|
# Tuned on GB300 with DSv4 row widths.
|
|
_TMA_BULK_STORE_MIN_LOCS = 768
|
|
|
|
|
|
def set_mla_kv_buffer_triton(
|
|
kv_buffer: torch.Tensor,
|
|
loc: torch.Tensor,
|
|
cache_k_nope: torch.Tensor,
|
|
cache_k_rope: torch.Tensor,
|
|
):
|
|
"""Dispatch MLA paged-KV scatter writes to the fastest available path.
|
|
|
|
Two paths, chosen on ``n_loc``:
|
|
|
|
- ``n_loc >= 768`` (and SM90+ with TMA-compatible row widths): JIT CUDA
|
|
kernel where each warp loads one (nope, rope) row into shared memory and
|
|
issues a single ``cp.async.bulk.global.shared::cta`` store to scatter the
|
|
row at ``kv_buffer[loc[item]]``. Wins at large bs because it packs 4-8
|
|
items per CTA, drastically reducing the CTA count vs single-CTA-per-loc.
|
|
- Otherwise: Triton kernel with ``BLOCK = next_pow2(nope_dim + rope_dim)``,
|
|
i.e. one CTA per loc covering the entire row in one tile. Wins at small
|
|
bs because there's no per-loc CTA fan-out (5x fewer CTAs than the old
|
|
BLOCK=128 dispatch) and the row-spanning block makes the boundary branch
|
|
a one-shot per CTA. This is also the path for SM<90 and for shapes that
|
|
violate the TMA 16-byte alignment.
|
|
|
|
Speedup vs the legacy BLOCK=128 Triton kernel on GB300 (BF16, nope=512,
|
|
rope=64): ~1.05x at bs=8, ~1.5x at bs=128, 3.5x at bs=512, **11.7x at
|
|
bs=16384**.
|
|
|
|
Name retained for caller compatibility; the implementation is no longer
|
|
Triton-only.
|
|
"""
|
|
from sglang.jit_kernel.set_mla_kv_buffer import (
|
|
can_use_set_mla_kv_buffer,
|
|
)
|
|
from sglang.jit_kernel.set_mla_kv_buffer import (
|
|
set_mla_kv_buffer as jit_set_mla_kv_buffer,
|
|
)
|
|
|
|
n_loc = loc.numel()
|
|
nope_bytes = cache_k_nope.shape[-1] * cache_k_nope.element_size()
|
|
rope_bytes = cache_k_rope.shape[-1] * cache_k_rope.element_size()
|
|
if (
|
|
n_loc >= _TMA_BULK_STORE_MIN_LOCS
|
|
and is_arch_support_pdl()
|
|
and can_use_set_mla_kv_buffer(nope_bytes, rope_bytes)
|
|
and not get_parallel().dcp_enabled
|
|
):
|
|
jit_set_mla_kv_buffer(kv_buffer, loc, cache_k_nope, cache_k_rope)
|
|
return
|
|
|
|
# Fallback: Triton with BLOCK = next_pow2(total_dim). One CTA per loc; the
|
|
# whole row in one tile (the existing 3-way nope/rope/boundary branch in
|
|
# ``set_mla_kv_buffer_kernel`` handles the over-allocation past total_dim
|
|
# via the offs<total_dim mask). Beats BLOCK=128 by 60-2700 ns across the
|
|
# 2 <= bs <= 512 range on GB300.
|
|
nope_dim = cache_k_nope.shape[-1]
|
|
rope_dim = cache_k_rope.shape[-1]
|
|
total_dim = nope_dim + rope_dim
|
|
BLOCK = triton.next_power_of_2(total_dim)
|
|
grid = (n_loc, 1)
|
|
pdl_kwargs = {"USE_GDC": True, "launch_pdl": True} if is_arch_support_pdl() else {}
|
|
set_mla_kv_buffer_kernel[grid](
|
|
kv_buffer,
|
|
cache_k_nope,
|
|
cache_k_rope,
|
|
loc,
|
|
kv_buffer.stride(0),
|
|
cache_k_nope.stride(0),
|
|
cache_k_rope.stride(0),
|
|
nope_dim,
|
|
rope_dim,
|
|
BLOCK=BLOCK,
|
|
DCP_RANK=get_parallel().attn_dcp_rank,
|
|
DCP_WORLD_SIZE=get_parallel().attn_dcp_size,
|
|
**pdl_kwargs,
|
|
)
|
|
|
|
|
|
@triton.jit
|
|
def set_mla_kv_buffer_fp8_quant_kernel(
|
|
kv_buffer_fp8_ptr,
|
|
cache_k_nope_ptr,
|
|
cache_k_rope_ptr,
|
|
loc_ptr,
|
|
buffer_stride: tl.constexpr,
|
|
nope_stride: tl.constexpr,
|
|
rope_stride: tl.constexpr,
|
|
nope_dim: tl.constexpr,
|
|
rope_dim: tl.constexpr,
|
|
BLOCK: tl.constexpr,
|
|
USE_GDC: tl.constexpr = False,
|
|
):
|
|
"""Fuse BF16/FP16->FP8 cast with paged KV write."""
|
|
pid_loc = tl.program_id(0)
|
|
pid_blk = tl.program_id(1)
|
|
|
|
base = pid_blk * BLOCK
|
|
offs = base + tl.arange(0, BLOCK)
|
|
total_dim = nope_dim + rope_dim
|
|
mask = offs < total_dim
|
|
|
|
if USE_GDC:
|
|
tl.extra.cuda.gdc_wait()
|
|
|
|
loc = tl.load(loc_ptr + pid_loc).to(tl.int64)
|
|
dst_ptr = kv_buffer_fp8_ptr + loc * buffer_stride + offs
|
|
|
|
if base + BLOCK <= nope_dim:
|
|
src = tl.load(
|
|
cache_k_nope_ptr + pid_loc * nope_stride + offs,
|
|
mask=mask,
|
|
other=0.0,
|
|
)
|
|
elif base >= nope_dim:
|
|
offs_rope = offs - nope_dim
|
|
src = tl.load(
|
|
cache_k_rope_ptr + pid_loc * rope_stride + offs_rope,
|
|
mask=mask,
|
|
other=0.0,
|
|
)
|
|
else:
|
|
is_nope = offs < nope_dim
|
|
src_nope = tl.load(
|
|
cache_k_nope_ptr + pid_loc * nope_stride + offs,
|
|
mask=mask & is_nope,
|
|
other=0.0,
|
|
)
|
|
src_rope = tl.load(
|
|
cache_k_rope_ptr + pid_loc * rope_stride + (offs - nope_dim),
|
|
mask=mask & ~is_nope,
|
|
other=0.0,
|
|
)
|
|
src = tl.where(is_nope, src_nope, src_rope)
|
|
|
|
# Destination pointer is FP8-typed view; tl.store performs downcast.
|
|
tl.store(dst_ptr, src, mask=mask)
|
|
|
|
if USE_GDC:
|
|
tl.extra.cuda.gdc_launch_dependents()
|
|
|
|
|
|
def set_mla_kv_buffer_triton_fp8_quant(
|
|
kv_buffer: torch.Tensor,
|
|
loc: torch.Tensor,
|
|
cache_k_nope: torch.Tensor,
|
|
cache_k_rope: torch.Tensor,
|
|
fp8_dtype: torch.dtype,
|
|
):
|
|
"""Fuse BF16/FP16 MLA K quantization with paged KV write."""
|
|
kv_buffer_fp8 = kv_buffer.view(fp8_dtype)
|
|
|
|
nope_dim = cache_k_nope.shape[-1]
|
|
rope_dim = cache_k_rope.shape[-1]
|
|
total_dim = nope_dim + rope_dim
|
|
BLOCK = 128
|
|
n_loc = loc.numel()
|
|
grid = (n_loc, triton.cdiv(total_dim, BLOCK))
|
|
|
|
pdl_kwargs = {"USE_GDC": True, "launch_pdl": True} if is_arch_support_pdl() else {}
|
|
|
|
set_mla_kv_buffer_fp8_quant_kernel[grid](
|
|
kv_buffer_fp8,
|
|
cache_k_nope,
|
|
cache_k_rope,
|
|
loc,
|
|
kv_buffer_fp8.stride(0),
|
|
cache_k_nope.stride(0),
|
|
cache_k_rope.stride(0),
|
|
nope_dim,
|
|
rope_dim,
|
|
BLOCK=BLOCK,
|
|
**pdl_kwargs,
|
|
)
|
|
|
|
|
|
@triton.jit
|
|
def set_mla_kv_scale_buffer_kernel(
|
|
kv_buffer_ptr,
|
|
cache_k_nope_ptr,
|
|
cache_k_rope_ptr,
|
|
loc_ptr,
|
|
buffer_stride: tl.constexpr,
|
|
nope_stride: tl.constexpr,
|
|
rope_stride: tl.constexpr,
|
|
nope_dim: tl.constexpr,
|
|
rope_dim: tl.constexpr,
|
|
BLOCK: tl.constexpr,
|
|
):
|
|
pid_loc = tl.program_id(0)
|
|
pid_blk = tl.program_id(1)
|
|
|
|
base = pid_blk * BLOCK
|
|
offs = base + tl.arange(0, BLOCK)
|
|
total_dim = nope_dim + rope_dim
|
|
mask = offs < total_dim # Make sure don't cross the boundary
|
|
|
|
loc = tl.load(loc_ptr + pid_loc)
|
|
dst_ptr = kv_buffer_ptr + loc * buffer_stride + offs
|
|
|
|
# Check each offs should read 'nope' or 'rope'
|
|
is_nope = offs < nope_dim
|
|
src_nope = tl.load(
|
|
cache_k_nope_ptr + pid_loc * nope_stride + offs, mask=mask & is_nope, other=0.0
|
|
)
|
|
src_rope = tl.load(
|
|
cache_k_rope_ptr + pid_loc * rope_stride + (offs - nope_dim),
|
|
mask=mask & ~is_nope,
|
|
other=0.0,
|
|
)
|
|
|
|
# Combine nope + rope
|
|
src = src_nope + src_rope
|
|
tl.store(dst_ptr, src, mask=mask)
|
|
|
|
|
|
def set_mla_kv_scale_buffer_triton(
|
|
kv_buffer: torch.Tensor,
|
|
loc: torch.Tensor,
|
|
cache_k_nope: torch.Tensor,
|
|
cache_k_rope: torch.Tensor,
|
|
):
|
|
nope_dim = cache_k_nope.shape[-1]
|
|
rope_dim = cache_k_rope.shape[-1]
|
|
total_dim = nope_dim + rope_dim
|
|
BLOCK = 128 # Keep origin, works for smaller total_dim as well.
|
|
n_loc = loc.numel()
|
|
grid = (n_loc, triton.cdiv(total_dim, BLOCK))
|
|
|
|
set_mla_kv_scale_buffer_kernel[grid](
|
|
kv_buffer,
|
|
cache_k_nope,
|
|
cache_k_rope,
|
|
loc,
|
|
kv_buffer.stride(0),
|
|
cache_k_nope.stride(0),
|
|
cache_k_rope.stride(0),
|
|
nope_dim,
|
|
rope_dim,
|
|
BLOCK=BLOCK,
|
|
)
|
|
|
|
|
|
@triton.jit
|
|
def get_mla_kv_buffer_kernel(
|
|
kv_buffer_ptr,
|
|
cache_k_nope_ptr,
|
|
cache_k_rope_ptr,
|
|
loc_ptr,
|
|
buffer_stride: tl.constexpr,
|
|
nope_stride: tl.constexpr,
|
|
rope_stride: tl.constexpr,
|
|
nope_dim: tl.constexpr,
|
|
rope_dim: tl.constexpr,
|
|
):
|
|
pid_loc = tl.program_id(0)
|
|
loc = tl.load(loc_ptr + pid_loc).to(tl.int64)
|
|
loc_src_ptr = kv_buffer_ptr + loc * buffer_stride
|
|
|
|
nope_offs = tl.arange(0, nope_dim)
|
|
nope_src_ptr = loc_src_ptr + nope_offs
|
|
nope_src = tl.load(nope_src_ptr)
|
|
|
|
tl.store(
|
|
cache_k_nope_ptr + pid_loc * nope_stride + nope_offs,
|
|
nope_src,
|
|
)
|
|
|
|
rope_offs = tl.arange(0, rope_dim)
|
|
rope_src_ptr = loc_src_ptr + nope_dim + rope_offs
|
|
rope_src = tl.load(rope_src_ptr)
|
|
tl.store(
|
|
cache_k_rope_ptr + pid_loc * rope_stride + rope_offs,
|
|
rope_src,
|
|
)
|
|
|
|
|
|
def get_mla_kv_buffer_triton(
|
|
kv_buffer: torch.Tensor,
|
|
loc: torch.Tensor,
|
|
cache_k_nope: torch.Tensor,
|
|
cache_k_rope: torch.Tensor,
|
|
):
|
|
# The source data type will be implicitly converted to the target data type.
|
|
nope_dim = cache_k_nope.shape[-1] # 512
|
|
rope_dim = cache_k_rope.shape[-1] # 64
|
|
n_loc = loc.numel()
|
|
grid = (n_loc,)
|
|
|
|
get_mla_kv_buffer_kernel[grid](
|
|
kv_buffer,
|
|
cache_k_nope,
|
|
cache_k_rope,
|
|
loc,
|
|
kv_buffer.stride(0),
|
|
cache_k_nope.stride(0),
|
|
cache_k_rope.stride(0),
|
|
nope_dim,
|
|
rope_dim,
|
|
)
|