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
391 lines
11 KiB
Python
391 lines
11 KiB
Python
import torch
|
|
import triton
|
|
import triton.language as tl
|
|
|
|
|
|
@triton.jit
|
|
def pad_sequence_with_mask_kernel(
|
|
input_ptr, # (total_tokens, hidden)
|
|
offsets_ptr, # (B,)
|
|
lengths_ptr, # (B,)
|
|
output_ptr, # (B, max_len, hidden)
|
|
mask_ptr, # (B, max_len)
|
|
max_len,
|
|
hidden_dim,
|
|
BLOCK_M: tl.constexpr, # seq block
|
|
BLOCK_D: tl.constexpr, # hidden block
|
|
):
|
|
b = tl.program_id(0) # batch index
|
|
m = tl.program_id(1) # seq block index
|
|
|
|
offset = tl.load(offsets_ptr + b)
|
|
length = tl.load(lengths_ptr + b)
|
|
|
|
seq_ids = m * BLOCK_M + tl.arange(0, BLOCK_M)
|
|
hid_ids = tl.arange(0, BLOCK_D)
|
|
|
|
seq_mask = seq_ids < max_len
|
|
valid_token = seq_ids < length
|
|
|
|
# input index
|
|
in_token = offset + seq_ids
|
|
in_ptr = input_ptr + in_token[:, None] * hidden_dim + hid_ids[None, :]
|
|
|
|
# output index
|
|
out_ptr = (
|
|
output_ptr
|
|
+ b * max_len * hidden_dim
|
|
+ seq_ids[:, None] * hidden_dim
|
|
+ hid_ids[None, :]
|
|
)
|
|
|
|
values = tl.load(
|
|
in_ptr,
|
|
mask=valid_token[:, None] & (hid_ids[None, :] < hidden_dim),
|
|
other=0.0,
|
|
)
|
|
|
|
tl.store(
|
|
out_ptr,
|
|
values,
|
|
mask=seq_mask[:, None] & (hid_ids[None, :] < hidden_dim),
|
|
)
|
|
|
|
# attention mask
|
|
if tl.program_id(2) == 0:
|
|
mask_out_ptr = mask_ptr + b * max_len + seq_ids
|
|
tl.store(mask_out_ptr, valid_token, mask=seq_mask)
|
|
|
|
|
|
def pad_sequence_with_mask(
|
|
input_emb, # (total_tokens, hidden)
|
|
offsets, # (B,)
|
|
lengths, # (B,)
|
|
max_len,
|
|
):
|
|
B = offsets.shape[0]
|
|
hidden_dim = input_emb.shape[1]
|
|
|
|
output = torch.zeros(
|
|
(B, max_len, hidden_dim),
|
|
device=input_emb.device,
|
|
dtype=input_emb.dtype,
|
|
)
|
|
attn_mask = torch.empty(
|
|
(B * max_len),
|
|
device=input_emb.device,
|
|
dtype=torch.bool,
|
|
)
|
|
|
|
BLOCK_D = triton.next_power_of_2(hidden_dim)
|
|
BLOCK_M = triton.next_power_of_2(max_len)
|
|
|
|
grid = (
|
|
B,
|
|
triton.cdiv(max_len, BLOCK_M),
|
|
1,
|
|
)
|
|
|
|
pad_sequence_with_mask_kernel[grid](
|
|
input_emb,
|
|
offsets,
|
|
lengths,
|
|
output,
|
|
attn_mask,
|
|
max_len,
|
|
hidden_dim,
|
|
BLOCK_M=BLOCK_M,
|
|
BLOCK_D=BLOCK_D,
|
|
)
|
|
|
|
return B, output, attn_mask
|
|
|
|
|
|
@triton.jit
|
|
def pad_draft_extend_query_kernel(
|
|
q_ptr, # Input query tensor [total_seq_len, num_heads, head_dim]
|
|
padded_q_ptr, # Output padded query tensor [batch_size, max_seq_len, num_heads, head_dim]
|
|
seq_lens_q_ptr, # Sequence lengths for each sequence [batch_size]
|
|
cumsum_ptr, # Cumulative sum of sequence lengths [batch_size + 1]
|
|
batch_size,
|
|
max_seq_len,
|
|
num_heads,
|
|
head_dim,
|
|
BLOCK_SIZE: tl.constexpr,
|
|
):
|
|
"""Triton kernel for padding draft extended query tensor with parallelized head and dim processing."""
|
|
# Use 3D program IDs: (batch_seq, head_block, dim_block)
|
|
batch_seq_pid = tl.program_id(0)
|
|
head_pid = tl.program_id(1)
|
|
dim_pid = tl.program_id(2)
|
|
|
|
batch_id = batch_seq_pid // max_seq_len
|
|
seq_pos = batch_seq_pid % max_seq_len
|
|
|
|
if batch_id >= batch_size:
|
|
return
|
|
|
|
# Load sequence length for this batch
|
|
seq_len = tl.load(seq_lens_q_ptr + batch_id)
|
|
|
|
if seq_pos >= seq_len:
|
|
return
|
|
|
|
# Load cumulative sum to get start position in input tensor
|
|
input_start = tl.load(cumsum_ptr + batch_id)
|
|
input_pos = input_start + seq_pos
|
|
|
|
# Calculate head and dim block ranges
|
|
head_start = head_pid * BLOCK_SIZE
|
|
head_end = tl.minimum(head_start + BLOCK_SIZE, num_heads)
|
|
head_mask = tl.arange(0, BLOCK_SIZE) < (head_end - head_start)
|
|
|
|
dim_start = dim_pid * BLOCK_SIZE
|
|
dim_end = tl.minimum(dim_start + BLOCK_SIZE, head_dim)
|
|
dim_mask = tl.arange(0, BLOCK_SIZE) < (dim_end - dim_start)
|
|
|
|
# Calculate input offset
|
|
input_offset = (
|
|
input_pos * num_heads * head_dim
|
|
+ (head_start + tl.arange(0, BLOCK_SIZE))[:, None] * head_dim
|
|
+ (dim_start + tl.arange(0, BLOCK_SIZE))[None, :]
|
|
)
|
|
|
|
# Load data
|
|
data = tl.load(
|
|
q_ptr + input_offset,
|
|
mask=head_mask[:, None] & dim_mask[None, :],
|
|
other=0.0,
|
|
)
|
|
|
|
# Calculate output offset
|
|
output_offset = (
|
|
batch_id * max_seq_len * num_heads * head_dim
|
|
+ seq_pos * num_heads * head_dim
|
|
+ (head_start + tl.arange(0, BLOCK_SIZE))[:, None] * head_dim
|
|
+ (dim_start + tl.arange(0, BLOCK_SIZE))[None, :]
|
|
)
|
|
|
|
# Store data
|
|
tl.store(
|
|
padded_q_ptr + output_offset,
|
|
data,
|
|
mask=head_mask[:, None] & dim_mask[None, :],
|
|
)
|
|
|
|
|
|
def pad_draft_extend_query(
|
|
q: torch.Tensor,
|
|
padded_q: torch.Tensor,
|
|
seq_lens_q: torch.Tensor,
|
|
cu_seqlens_q: torch.Tensor,
|
|
) -> torch.Tensor:
|
|
"""Pad draft extended query using Triton kernel."""
|
|
batch_size = cu_seqlens_q.shape[0] - 1
|
|
max_seq_len_q = padded_q.shape[1]
|
|
num_heads = padded_q.shape[2]
|
|
head_dim = padded_q.shape[3]
|
|
|
|
# Launch Triton kernel with 3D grid for parallelized head and dim processing
|
|
BLOCK_SIZE = 64
|
|
num_head_blocks = triton.cdiv(num_heads, BLOCK_SIZE)
|
|
num_dim_blocks = triton.cdiv(head_dim, BLOCK_SIZE)
|
|
grid = (batch_size * max_seq_len_q, num_head_blocks, num_dim_blocks)
|
|
|
|
pad_draft_extend_query_kernel[grid](
|
|
q_ptr=q,
|
|
padded_q_ptr=padded_q,
|
|
seq_lens_q_ptr=seq_lens_q,
|
|
cumsum_ptr=cu_seqlens_q,
|
|
batch_size=batch_size,
|
|
max_seq_len=max_seq_len_q,
|
|
num_heads=num_heads,
|
|
head_dim=head_dim,
|
|
BLOCK_SIZE=BLOCK_SIZE,
|
|
)
|
|
return padded_q
|
|
|
|
|
|
@triton.jit
|
|
def unpad_draft_extend_output_kernel(
|
|
raw_out_ptr, # Input raw output tensor (batch_size, token_per_batch, tp_q_head_num, v_head_dim)
|
|
output_ptr, # Output tensor (-1, tp_q_head_num, v_head_dim)
|
|
num_accept_tokens_ptr, # Accept lengths for each sequence [batch_size]
|
|
cumsum_ptr, # Cumulative sum of accept lengths [batch_size + 1]
|
|
batch_size,
|
|
token_per_batch,
|
|
tp_q_head_num,
|
|
v_head_dim,
|
|
BLOCK_SIZE: tl.constexpr,
|
|
):
|
|
"""Triton kernel for unpadding draft extended output tensor with parallelized head and dim processing."""
|
|
batch_seq_pid = tl.program_id(0)
|
|
head_pid = tl.program_id(1)
|
|
dim_pid = tl.program_id(2)
|
|
|
|
batch_id = batch_seq_pid // token_per_batch
|
|
seq_pos = batch_seq_pid % token_per_batch
|
|
|
|
if batch_id >= batch_size:
|
|
return
|
|
|
|
# Load accept length for this batch
|
|
accept_len = tl.load(num_accept_tokens_ptr + batch_id)
|
|
|
|
if seq_pos >= accept_len:
|
|
return
|
|
|
|
# Load cumulative sum to get start position in output tensor
|
|
output_start = tl.load(cumsum_ptr + batch_id)
|
|
output_pos = output_start + seq_pos
|
|
|
|
# Calculate head and dim block ranges
|
|
head_start = head_pid * BLOCK_SIZE
|
|
head_end = tl.minimum(head_start + BLOCK_SIZE, tp_q_head_num)
|
|
head_mask = tl.arange(0, BLOCK_SIZE) < (head_end - head_start)
|
|
|
|
dim_start = dim_pid * BLOCK_SIZE
|
|
dim_end = tl.minimum(dim_start + BLOCK_SIZE, v_head_dim)
|
|
dim_mask = tl.arange(0, BLOCK_SIZE) < (dim_end - dim_start)
|
|
|
|
# Calculate input offset: (batch_id, seq_pos, head_id, dim_id)
|
|
input_offset = (
|
|
batch_id * token_per_batch * tp_q_head_num * v_head_dim
|
|
+ seq_pos * tp_q_head_num * v_head_dim
|
|
+ (head_start + tl.arange(0, BLOCK_SIZE))[:, None] * v_head_dim
|
|
+ (dim_start + tl.arange(0, BLOCK_SIZE))[None, :]
|
|
)
|
|
|
|
# Load data
|
|
data = tl.load(
|
|
raw_out_ptr + input_offset,
|
|
mask=head_mask[:, None] & dim_mask[None, :],
|
|
other=0.0,
|
|
)
|
|
|
|
output_offset = (
|
|
output_pos * tp_q_head_num * v_head_dim
|
|
+ (head_start + tl.arange(0, BLOCK_SIZE))[:, None] * v_head_dim
|
|
+ (dim_start + tl.arange(0, BLOCK_SIZE))[None, :]
|
|
)
|
|
|
|
# Store data
|
|
tl.store(
|
|
output_ptr + output_offset,
|
|
data,
|
|
mask=head_mask[:, None] & dim_mask[None, :],
|
|
)
|
|
|
|
|
|
def unpad_draft_extend_output(
|
|
raw_out: torch.Tensor,
|
|
cu_seqlens_q: torch.Tensor,
|
|
seq_lens_q: torch.Tensor,
|
|
sum_seq_lens_q: int,
|
|
unpad_output_buffer: torch.Tensor | None = None,
|
|
) -> torch.Tensor:
|
|
"""Unpad draft extended output using Triton kernel."""
|
|
# raw_out: (batch_size, token_per_batch, layer.tp_q_head_num, layer.v_head_dim)
|
|
batch_size = seq_lens_q.shape[0]
|
|
token_per_batch = raw_out.shape[1] # max_seq_len
|
|
tp_q_head_num = raw_out.shape[2] # num_heads
|
|
v_head_dim = raw_out.shape[3] # head_dim
|
|
total_tokens = sum_seq_lens_q
|
|
|
|
# Check if we're in CUDA graph mode (buffers are pre-allocated)
|
|
if unpad_output_buffer is not None:
|
|
# Use pre-allocated buffer for CUDA graph compatibility
|
|
output = unpad_output_buffer[:total_tokens, :, :].to(dtype=raw_out.dtype)
|
|
else:
|
|
# Dynamic allocation for non-CUDA graph mode
|
|
output = torch.empty(
|
|
(total_tokens, tp_q_head_num, v_head_dim),
|
|
dtype=raw_out.dtype,
|
|
device=raw_out.device,
|
|
)
|
|
|
|
# Launch Triton kernel with 3D grid for parallelized head and dim processing
|
|
BLOCK_SIZE = 64
|
|
num_head_blocks = triton.cdiv(tp_q_head_num, BLOCK_SIZE)
|
|
num_dim_blocks = triton.cdiv(v_head_dim, BLOCK_SIZE)
|
|
grid = (batch_size * token_per_batch, num_head_blocks, num_dim_blocks)
|
|
|
|
unpad_draft_extend_output_kernel[grid](
|
|
raw_out_ptr=raw_out,
|
|
output_ptr=output,
|
|
num_accept_tokens_ptr=seq_lens_q,
|
|
cumsum_ptr=cu_seqlens_q,
|
|
batch_size=batch_size,
|
|
token_per_batch=token_per_batch,
|
|
tp_q_head_num=tp_q_head_num,
|
|
v_head_dim=v_head_dim,
|
|
BLOCK_SIZE=BLOCK_SIZE,
|
|
)
|
|
return output[:total_tokens, :, :]
|
|
|
|
|
|
@triton.jit
|
|
def seqlens_expand_kernel(
|
|
extend_seq_lens_ptr, # [N]
|
|
seq_lens_ptr, # [N]
|
|
offsets_ptr, # [N+1]
|
|
output_ptr, # [sum(extend_seq_lens)]
|
|
N,
|
|
BLOCK: tl.constexpr,
|
|
):
|
|
pid = tl.program_id(0)
|
|
|
|
if pid >= N:
|
|
return
|
|
|
|
qo_len = tl.load(extend_seq_lens_ptr + pid)
|
|
kv_len = tl.load(seq_lens_ptr + pid)
|
|
|
|
start = kv_len - qo_len + 1
|
|
out_offset = tl.load(offsets_ptr + pid)
|
|
|
|
offs = tl.arange(0, BLOCK)
|
|
mask = offs < qo_len
|
|
|
|
# Clamp to >= 0: rows with kv_len < qo_len (DP-padded / idle-companion
|
|
# rows whose kv is the CUDA-graph fill value) would otherwise produce
|
|
# negative lengths, which unsigned consumers (e.g. the top-k v2 kernel,
|
|
# which reads lengths as uint32) turn into ~4e9-token lengths and an
|
|
# illegal memory access.
|
|
values = tl.maximum(start + offs, 0)
|
|
tl.store(output_ptr + out_offset + offs, values, mask=mask)
|
|
|
|
|
|
def seqlens_expand_triton(
|
|
extend_seq_lens: torch.Tensor,
|
|
seq_lens: torch.Tensor,
|
|
total_len: int,
|
|
max_q_len: int,
|
|
):
|
|
"""
|
|
extend_seq_lens: [N], int32, CUDA
|
|
seq_lens: [N], int32, CUDA
|
|
"""
|
|
assert extend_seq_lens.is_cuda
|
|
assert seq_lens.is_cuda
|
|
|
|
N = extend_seq_lens.numel()
|
|
|
|
offsets = torch.zeros(N + 1, device=extend_seq_lens.device, dtype=torch.int32)
|
|
offsets[1:] = torch.cumsum(extend_seq_lens, dim=0)
|
|
output = torch.empty(total_len, device=extend_seq_lens.device, dtype=torch.int32)
|
|
|
|
BLOCK = triton.next_power_of_2(max_q_len)
|
|
grid = (N,)
|
|
|
|
seqlens_expand_kernel[grid](
|
|
extend_seq_lens,
|
|
seq_lens,
|
|
offsets,
|
|
output,
|
|
N,
|
|
BLOCK=BLOCK,
|
|
)
|
|
|
|
return output
|