Files
wehub-resource-sync 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
chore: import upstream snapshot with attribution
2026-07-13 12:38:16 +08:00

192 lines
6.3 KiB
Python

"""Fused Triton pack/scatter kernels for the varlen mask path.
Used by ``USPAttention.forward`` masked branch to gather Q/K/V at valid
positions and scatter the FA output back to the dense ``[B, S, H, D]`` layout.
"""
from __future__ import annotations
import torch
import triton # type: ignore
import triton.language as tl # type: ignore
# ---------------------------------------------------------------------------
# Pack (unpad) — gather Q/K/V at indices into packed [total_valid, H, D]
# ---------------------------------------------------------------------------
@triton.jit
def _fused_pack_qkv_kernel(
Q_ptr,
K_ptr,
V_ptr,
Q_unpad_ptr,
K_unpad_ptr,
V_unpad_ptr,
indices_ptr,
HD, # H * D, flattened feature dim
src_row_stride, # stride between rows in Q/K/V (B*S row -> next row)
dst_row_stride, # stride in Q_unpad/K_unpad/V_unpad
BLOCK_HD: tl.constexpr,
):
"""One program per packed row; copies Q[src], K[src], V[src] to dst row."""
out_row = tl.program_id(0)
src_row = tl.load(indices_ptr + out_row).to(tl.int64)
cols = tl.arange(0, BLOCK_HD)
col_mask = cols < HD
src_offset = src_row * src_row_stride + cols
dst_offset = out_row * dst_row_stride + cols
q_val = tl.load(Q_ptr + src_offset, mask=col_mask)
k_val = tl.load(K_ptr + src_offset, mask=col_mask)
v_val = tl.load(V_ptr + src_offset, mask=col_mask)
tl.store(Q_unpad_ptr + dst_offset, q_val, mask=col_mask)
tl.store(K_unpad_ptr + dst_offset, k_val, mask=col_mask)
tl.store(V_unpad_ptr + dst_offset, v_val, mask=col_mask)
def fused_pack_qkv(
q: torch.Tensor,
k: torch.Tensor,
v: torch.Tensor,
indices: torch.Tensor,
) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
"""Pack ``[B, S, H, D]`` Q/K/V at ``indices`` into ``[total_valid, H, D]``.
``indices`` is the int64 flat ``B*S`` position for each kept token.
Non-contiguous inputs are made contiguous internally.
"""
assert q.shape == k.shape == v.shape, "Q/K/V must share shape"
assert q.dtype == k.dtype == v.dtype, "Q/K/V must share dtype"
assert q.dim() == 4, "Q/K/V must be [B, S, H, D]"
assert indices.dtype in (torch.int32, torch.int64)
q = q.contiguous()
k = k.contiguous()
v = v.contiguous()
bs, seq, num_heads, head_dim = q.shape
hd = num_heads * head_dim
n_valid = indices.shape[0]
if n_valid == 0:
return (
q.new_empty(0, num_heads, head_dim),
k.new_empty(0, num_heads, head_dim),
v.new_empty(0, num_heads, head_dim),
)
block_hd = triton.next_power_of_2(hd)
q_flat = q.view(bs * seq, hd)
k_flat = k.view(bs * seq, hd)
v_flat = v.view(bs * seq, hd)
q_unpad = torch.empty(n_valid, hd, dtype=q.dtype, device=q.device)
k_unpad = torch.empty(n_valid, hd, dtype=k.dtype, device=k.device)
v_unpad = torch.empty(n_valid, hd, dtype=v.dtype, device=v.device)
with torch.get_device_module().device(q.device):
_fused_pack_qkv_kernel[(n_valid,)](
q_flat,
k_flat,
v_flat,
q_unpad,
k_unpad,
v_unpad,
indices,
hd,
q_flat.stride(0),
q_unpad.stride(0),
BLOCK_HD=block_hd,
)
return (
q_unpad.view(n_valid, num_heads, head_dim),
k_unpad.view(n_valid, num_heads, head_dim),
v_unpad.view(n_valid, num_heads, head_dim),
)
# ---------------------------------------------------------------------------
# Scatter (pad) — write packed output to [B, S, H, D] with zeros at invalid
# ---------------------------------------------------------------------------
@triton.jit
def _fused_scatter_to_padded_kernel(
Out_unpad_ptr,
Out_padded_ptr,
inv_indices_ptr, # [B*S]: pack idx for valid row, -1 for invalid
HD,
src_row_stride,
dst_row_stride,
BLOCK_HD: tl.constexpr,
):
"""One program per padded row; writes from pack or zeros."""
pad_row = tl.program_id(0)
inv_idx = tl.load(inv_indices_ptr + pad_row).to(tl.int64)
cols = tl.arange(0, BLOCK_HD)
col_mask = cols < HD
valid = inv_idx >= 0
safe_idx = tl.where(valid, inv_idx, 0)
src_offset = safe_idx * src_row_stride + cols
dst_offset = pad_row * dst_row_stride + cols
val = tl.load(Out_unpad_ptr + src_offset, mask=col_mask & valid, other=0.0)
tl.store(Out_padded_ptr + dst_offset, val, mask=col_mask)
def fused_scatter_to_padded(
out_unpad: torch.Tensor,
inv_indices: torch.Tensor,
batch_size: int,
seqlen: int,
) -> torch.Tensor:
"""Scatter packed varlen output back to ``[B, S, H, D]`` with zero padding.
``inv_indices`` is ``[B*S]`` giving the pack row index for each padded
position (``-1`` for padding). Non-contiguous ``out_unpad`` is made contiguous.
"""
assert out_unpad.dim() == 3, "out_unpad must be [total_valid, H, D]"
assert inv_indices.shape == (batch_size * seqlen,)
assert inv_indices.dtype in (torch.int32, torch.int64)
out_unpad = out_unpad.contiguous()
_, num_heads, head_dim = out_unpad.shape
hd = num_heads * head_dim
block_hd = triton.next_power_of_2(hd)
out_padded = torch.empty(
batch_size * seqlen, hd, dtype=out_unpad.dtype, device=out_unpad.device
)
out_unpad_flat = out_unpad.view(-1, hd)
with torch.get_device_module().device(out_unpad.device):
_fused_scatter_to_padded_kernel[(batch_size * seqlen,)](
out_unpad_flat,
out_padded,
inv_indices,
hd,
out_unpad_flat.stride(0),
out_padded.stride(0),
BLOCK_HD=block_hd,
)
return out_padded.view(batch_size, seqlen, num_heads, head_dim)
# ---------------------------------------------------------------------------
# Inverse-index builder (called once per request alongside indices)
# ---------------------------------------------------------------------------
def build_inv_indices(indices: torch.Tensor, total_rows: int) -> torch.Tensor:
"""For each padded row in ``[B*S]``, return its pack index or ``-1``."""
n_valid = indices.shape[0]
inv = torch.full((total_rows,), -1, dtype=torch.int32, device=indices.device)
inv[indices.long()] = torch.arange(
n_valid, dtype=torch.int32, device=indices.device
)
return inv