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

248 lines
8.9 KiB
Python

from __future__ import annotations
import torch
from sglang.jit_kernel.kv_canary import consts
from sglang.jit_kernel.kv_canary.consts import splitmix64, splitmix64_mix3
from sglang.jit_kernel.kv_canary.verify import (
RealKvSource,
VerifyOrWriteContext,
VerifyPlan,
)
_U64_MASK: int = (1 << 64) - 1
_I64_SIGN_BIT: int = 1 << 63
def launch_canary_verify_kernel_torch_reference(
*,
context: VerifyOrWriteContext,
plan: VerifyPlan,
check_verify_expected_token: bool,
) -> None:
canary_buf = context.canary_buf
kernel_kind = context.kernel_kind
violation_ring = context.violation_ring
violation_write_index = context.violation_write_index
slot_run_counter = context.slot_run_counter
kernel_run_counter = context.kernel_run_counter
real_kv_sources = context.real_kv_sources
real_kv_hash_mode = context.real_kv_hash_mode
work_device = torch.device("cpu")
kernel_run_counter.add_(1)
enable = int(plan.enable.detach().to("cpu").item())
if enable == 0:
return
num_valid = int(
plan.verify_slot_indices.new_empty(()).copy_(plan.verify_num_valid[0]).item()
)
capacity = int(plan.verify_slot_indices.shape[0])
active = max(0, min(num_valid, capacity))
if active <= 0:
return
slot_indices_host = plan.verify_slot_indices[:active].to(
device=work_device, dtype=torch.int64
)
if check_verify_expected_token:
expected_input_ids_host = plan.verify_expected_tokens[:active].to(
device=work_device, dtype=torch.int64
)
else:
expected_input_ids_host = torch.full(
(active,), -1, dtype=torch.int64, device=work_device
)
expected_positions_host = plan.verify_expected_positions[:active].to(
device=work_device, dtype=torch.int64
)
prev_slot_indices_host = plan.verify_prev_slot_indices[:active].to(
device=work_device, dtype=torch.int64
)
slot_run_counter.add_(active)
kept_slots: list[int] = []
kept_expected_positions: list[int] = []
kept_expected_input_ids: list[int] = []
kept_prev_slots: list[int] = []
for k in range(active):
s = int(slot_indices_host[k].item())
# Skip SGLang's padded-token dummy KV slot so unfilled req_to_token entries (zero-initialized) do not
# produce spurious chain_hash / position violations.
if s != consts.TOKEN_TO_KV_SLOT_PADDING:
kept_slots.append(s)
kept_expected_positions.append(int(expected_positions_host[k].item()))
kept_expected_input_ids.append(int(expected_input_ids_host[k].item()))
kept_prev_slots.append(int(prev_slot_indices_host[k].item()))
active = len(kept_slots)
if active <= 0:
return
slot_indices_list: list[int] = kept_slots
expected_positions_list: list[int] = kept_expected_positions
expected_input_ids_list: list[int] = kept_expected_input_ids
prev_slot_indices_list: list[int] = kept_prev_slots
buf_i64 = canary_buf.detach().to(device=work_device).contiguous().view(torch.int64)
slot_stride_i64 = int(buf_i64.shape[1])
if slot_stride_i64 < 4:
raise ValueError(
f"kv-canary: canary_buf slot stride must hold at least 4 int64 fields, got {slot_stride_i64}"
)
violation_rows: list[list[int]] = []
for k in range(active):
slot_idx = slot_indices_list[k]
expected_position = expected_positions_list[k]
expected_input_id = expected_input_ids_list[k]
prev_slot = prev_slot_indices_list[k]
stored_token = int(buf_i64[slot_idx, consts.CANARY_FIELD_TOKEN].item())
stored_position = int(buf_i64[slot_idx, consts.CANARY_FIELD_POSITION].item())
stored_chain_hash = int(buf_i64[slot_idx, consts.CANARY_FIELD_PREV_HASH].item())
stored_real_kv_hash = int(
buf_i64[slot_idx, consts.CANARY_FIELD_REAL_KV_HASH].item()
)
prev_reachable = prev_slot != consts.TOKEN_TO_KV_SLOT_PADDING
if prev_reachable:
expected_chain_hash = _to_signed_int64(
compute_slot_hash(buf_i64, prev_slot)
)
else:
expected_chain_hash = stored_chain_hash
expected_real_kv_hash_u64 = _compute_real_kv_hash_scalar(
slot_idx=slot_idx,
real_kv_sources=real_kv_sources,
real_kv_hash_mode=real_kv_hash_mode,
work_device=work_device,
)
expected_real_kv_hash = _to_signed_int64(expected_real_kv_hash_u64)
fail_reason = consts.FailReason(0)
if prev_reachable and stored_chain_hash != expected_chain_hash:
fail_reason |= consts.FailReason.VERIFY_CHAIN_HASH_MISMATCH
if check_verify_expected_token:
if expected_input_id != -1 and stored_token != expected_input_id:
fail_reason |= consts.FailReason.VERIFY_TOKEN_MISMATCH
if stored_position != expected_position:
fail_reason |= consts.FailReason.VERIFY_POSITION_MISMATCH
if stored_real_kv_hash != expected_real_kv_hash:
fail_reason |= consts.FailReason.VERIFY_REAL_KV_HASH_MISMATCH
if fail_reason != consts.FailReason(0):
row = [0] * consts.VIOLATION_FIELDS
row[consts.VIOLATION_FIELD_KERNEL_KIND] = int(kernel_kind)
row[consts.VIOLATION_FIELD_SLOT_IDX] = slot_idx
row[consts.VIOLATION_FIELD_POSITION] = stored_position
row[consts.VIOLATION_FIELD_STORED_TOKEN] = stored_token
row[consts.VIOLATION_FIELD_EXPECTED_TOKEN] = expected_input_id
row[consts.VIOLATION_FIELD_STORED_CHAIN_HASH] = stored_chain_hash
row[consts.VIOLATION_FIELD_EXPECTED_AUX] = expected_chain_hash
row[consts.VIOLATION_FIELD_FAIL_REASON_BITS] = int(fail_reason)
violation_rows.append(row)
if len(violation_rows) == 0:
return
num_new_violations = len(violation_rows)
base_idx = int(
violation_write_index.new_empty(()).copy_(violation_write_index[0]).item()
)
ring_capacity = int(violation_ring.shape[0])
new_rows = torch.zeros(
(num_new_violations, consts.VIOLATION_FIELDS), dtype=torch.int64
)
for v, row in enumerate(violation_rows):
for f in range(consts.VIOLATION_FIELDS):
new_rows[v, f] = row[f]
write_count_in_ring = max(0, min(num_new_violations, ring_capacity - base_idx))
if write_count_in_ring > 0:
ring_host = violation_ring.detach().to(device=work_device)
ring_host[base_idx : base_idx + write_count_in_ring, :] = new_rows[
:write_count_in_ring, :
]
violation_ring.copy_(ring_host.to(violation_ring.device))
violation_write_index[0] = violation_write_index[0] + num_new_violations
def _to_signed_int64(value: int) -> int:
value &= _U64_MASK
if value >= _I64_SIGN_BIT:
value -= 1 << 64
return value
def compute_slot_hash(buf_i64: torch.Tensor, source_slot_idx: int) -> int:
if source_slot_idx < 0:
return splitmix64(consts.CANARY_CHAIN_ANCHOR)
token = int(buf_i64[source_slot_idx, consts.CANARY_FIELD_TOKEN].item())
position = int(buf_i64[source_slot_idx, consts.CANARY_FIELD_POSITION].item())
prev_hash = int(buf_i64[source_slot_idx, consts.CANARY_FIELD_PREV_HASH].item())
return splitmix64_mix3(prev_hash, token, position)
def _compute_real_kv_hash_scalar(
*,
slot_idx: int,
real_kv_sources: tuple[RealKvSource, ...],
real_kv_hash_mode: consts.RealKvHashMode,
work_device: torch.device,
) -> int:
mode = int(real_kv_hash_mode)
if mode == int(consts.RealKvHashMode.NONE) or len(real_kv_sources) == 0:
return 0
acc: int = 0
for source in real_kv_sources:
page_size = source.page_size
num_bytes_per_token = source.num_bytes_per_token
read_bytes = source.read_bytes
tensor_u8 = (
source.tensor.detach().to(device=work_device).contiguous().view(torch.uint8)
)
row = slot_idx // page_size
col_within_page = slot_idx % page_size
col_start = col_within_page * num_bytes_per_token
effective_read_bytes = (
16 if mode == int(consts.RealKvHashMode.PARTIAL) else read_bytes
)
raw_bytes: list[int] = []
for b in range(effective_read_bytes):
raw_bytes.append(int(tensor_u8[row, col_start + b].item()))
source_hash = _splitmix64_fold_bytes_scalar(raw_bytes=raw_bytes)
combined = acc ^ source_hash
acc = splitmix64(combined)
return acc
def _splitmix64_fold_bytes_scalar(*, raw_bytes: list[int]) -> int:
read_bytes = len(raw_bytes)
pad = (8 - read_bytes % 8) % 8
padded = raw_bytes + [0] * pad
num_words = len(padded) // 8
acc: int = 0
for w in range(num_words):
word: int = 0
for k in range(8):
word |= padded[w * 8 + k] << (8 * k)
word &= _U64_MASK
acc = splitmix64(acc ^ word)
return acc