Prhub

#26817 Add real-data KV verification to the KV-canary

原始 PR 作者 fzyzcjy 合并时间 2026-05-31 09:58 文件变更 45 提交数 1 评论 1 代码增减 +2695 / -103

执行摘要

新增真实 KV 数据指纹验证到 KV-canary

在纯合成金丝雀基础上,增加对模型真实 KV 字节的哈希和验证,从而捕获实际缓存 KV 的损坏,而不仅仅是合成标记的异常。该功能是 KV-canary 体系的关键补充,使故障检测覆盖到真实数据层面。

建议深入阅读 RealKvSource 数据类及其工厂函数的设计,理解如何通过 page_sizenum_bytes_per_token 适配不同 KV 缓存布局。该 PR 是 KV-canary 功能线的关键一环,对了解 SGLang 的缓存可观测性架构有参考价值。

讨论亮点

本次 PR 无实质性 Review 讨论,作者提交后通过 CI 直接合并。唯一的评论来自 Gemini Code Assist 的每日配额警告,未涉及技术内容。

实现拆解

  1. 数据源抽象:在 python/sglang/jit_kernel/kv_canary/verify.py 中定义 RealKvSource 数据类,封装 tensorpage_sizenum_bytes_per_tokenread_bytes,并添加严格的 16 字节对齐校验(__post_init__);同时新增 RealKvHashMode 枚举(NONE/PARTIAL/ALL)。
  2. 源构造工厂与配置:在 python/sglang/srt/kv_canary/pool_patcher/buffer_alloc.py 中添加 resolve_real_kv_read_bytes 根据配置计算读取字节数,以及 make_row_sourcemake_packed_source 将不同布局的 KV 张量转化为 RealKvSource 元组,并对齐校验。
  3. CUDA 内核扩展:修改 write/verify CUDA 内核,新增对 field[3] 的 real_kv 哈希存储与验证,基于 splitmix64 算法,支持多 source 折叠。
  4. 运行时串联与扰动:通过 CanaryConfig 新增 real_kv_hash_mode,在 endpoint.py_resolve_real_kv_sources 中生成 sources 并传递;perturb/utils.py 新增 flip_random_source_byte_and_log 使扰动可直接作用于真实 KV 源。
  5. 测试覆盖:在 test_verify_hand.pytest_write_hand.py 中新增 TestRealKvHash 类覆盖所有模式和多 source 折叠场景;更新 test_self_unit_buffer_alloc.pytest_self_unit_perturb.py 验证新工具函数。
文件 模块 状态 重要度
python/sglang/jit_kernel/kv_canary/verify.py 内核层 modified 8.45
python/sglang/srt/kv_canary/pool_patcher/buffer_alloc.py 缓冲区分配 modified 8.35
python/sglang/srt/kv_canary/endpoint.py 端点层 modified 6.91
python/sglang/srt/kv_canary/perturb/utils.py 扰动工具 modified 7.59
python/sglang/jit_kernel/tests/kv_canary/test_verify_hand.py 验证测试 modified 7.52
python/sglang/srt/kv_canary/config.py 配置 modified 6.0

关键符号

RealKvSource.__post_init__ resolve_real_kv_read_bytes _clip_read_bytes_aligned make_row_source make_packed_source _resolve_real_kv_sources _compute_real_kv_hash_scalar flip_random_source_byte_and_log flip_first_byte_in_source launch_canary_write_kernel launch_canary_verify_kernel

关键源码片段

python/sglang/jit_kernel/kv_canary/verify.py core-logic

核心数据抽象:定义了 RealKvSource 类及其对齐校验逻辑,是后续一切操作的基础。

# 文件 : python/sglang/jit_kernel/kv_canary/verify.py
# 真实 KV 数据源抽象,描述 canary 应读取的实际 KV 字节片段
@dataclass(frozen=True, slots=True, kw_only=True)
class RealKvSource:
    tensor: torch.Tensor # 底层存储,至少 2 维,行内允许有空洞
    page_size: int # 每行打包的 slot 数,>= 1
    num_bytes_per_token: int # 每个 slot 在 dim-1 上的字节数,正 16 倍数
    read_bytes: int # 实际折叠进指纹的字节数,正 16 倍数且 <= num_bytes_per_token
​
    def __post_init__(self) -> None:
        # 对齐校验:所有关键参数必须为 16 的倍数
        if self.page_size < 1:
            raise ValueError(...)
        if self.num_bytes_per_token <= 0 or self.num_bytes_per_token % 16 != 0:
            raise ValueError(...)
        if self.read_bytes <= 0 or self.read_bytes > self.num_bytes_per_token or self.read_bytes % 16 != 0:
            raise ValueError(...)
        if self.tensor.ndim < 2:
            raise ValueError(...)
        row_stride_bytes = int(self.tensor.shape[1]) * self.tensor.element_size()
        if row_stride_bytes % 16 != 0:
            raise ValueError(...)
python/sglang/srt/kv_canary/pool_patcher/buffer_alloc.py dependency-wiring

源构造工厂:提供 resolve_real_kv_read_bytes、make_row_source 和 make_packed_source,将不同 KV 缓存布局适配为 RealKvSource 元组。

# 文件 : python/sglang/srt/kv_canary/pool_patcher/buffer_alloc.py
# 解析配置决定读取字节数
_PARTIAL_REAL_KV_READ_BYTES = 16
_REAL_KV_READ_ALIGN = 16def resolve_real_kv_read_bytes(config: CanaryConfig) -> int:
    if config.real_kv_hash_mode is RealKvHashMode.NONE:
        return 0
    if config.real_kv_hash_mode is RealKvHashMode.ALL:
        return sys.maxsize # 发送给内核,让其使用完整行长度
    return _PARTIAL_REAL_KV_READ_BYTES# 裁剪并校验读取字节数,确保 128 位对齐
def _clip_read_bytes_aligned(*, requested: int, num_bytes_per_token: int) -> int:
    # 要求每 token 字节数为 16 的倍数
    if num_bytes_per_token <= 0 or num_bytes_per_token % _REAL_KV_READ_ALIGN != 0:
        raise ValueError(...)
    if requested == 0:
        return 0
    if requested == sys.maxsize:
        return num_bytes_per_token
    if requested < 0 or requested > num_bytes_per_token:
        raise ValueError(...)
    if requested % _REAL_KV_READ_ALIGN != 0:
        raise ValueError(...)
    return requested# 为 row-major 布局构造 RealKvSource(page_size=1)
def make_row_source(*, layer_buffer: torch.Tensor, read_bytes: int) -> Tuple[RealKvSource, ...]:
    contiguous = layer_buffer.contiguous()
    num_slots = int(contiguous.shape[0])
    if num_slots == 0 or read_bytes == 0:
        return ()
    flat = contiguous.view(torch.uint8).reshape(num_slots, -1)
    num_bytes_per_token = int(flat.shape[1])
    clipped = _clip_read_bytes_aligned(requested=read_bytes, num_bytes_per_token=num_bytes_per_token)
    if clipped == 0:
        return ()
    return (RealKvSource(tensor=flat, page_size=1, num_bytes_per_token=num_bytes_per_token, read_bytes=clipped),)

评论区精华

没有提炼出高价值讨论线程

当前评论区没有形成足够清晰的争议点或结论,后续有更多讨论时会体现在这里。

风险与影响

  1. 性能开销:ALL 模式下需读取全部 KV 字节,可能增加推理延迟,建议非诊断场景保持默认 NONE。
  2. 对齐约束:128 位对齐要求严格,若 KV 缓存布局不符合可能导致内核异常。
  3. 配置依赖:新参数 --kv-canary-real-data 未设置时功能静默,用户可能误以为已启用。
  4. 模块耦合:RealKvSource 抽象与现有 CanaryBufferGroup、endpoint 等紧密耦合,后续改造需同步调整。

影响范围局限在 KV-canary 子系统,不影响核心推理路径(默认关闭)。用户可通过新参数启用诊断能力,团队需要维护额外的抽象层和测试套件。设计与代码质量较高,长期可维护性良好。

性能开销 对齐约束 配置依赖 模块耦合

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论