Prhub

#26819 Add the KV-canary perturb modes and PD-disaggregation e2e tests

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

执行摘要

新增 KV-canary 扰动模式与 PD 拆分端到端测试

PR body 指出需要增加 canary 自测扰动模式以及预填充-解码拆分的端到端测试,以验证 KV-canary 对真实 KV 篡改的检测能力。扰动模式模拟不同生命周期中的 KV 数据损坏(req_to_token 映射错误、正在使用的 slot、缓存的未使用 slot、以及刚写入的 slot),帮助提前发现缓存一致性问题。

本 PR 值得精读,因为其扰动设计覆盖了 KV 缓存的三种典型损坏场景(活跃使用、缓存孤立、刚写入),展示了一种利用 stream ordering 保证时序的实现方法;同时 slot_picker 中排除 out_cache_loc 避免与首次写入竞争的考虑值得借鉴。

讨论亮点

PR 无 review 讨论。唯一的评论来自 gemini-code-assist[bot] 的配额提示,无关。

实现拆解

  1. 新增 slot_picker.py 基础工具:提供 collect_active_slots 函数从 ForwardBatch 收集当前活跃请求的 req_to_token 槽位,并自动排除 out_cache_loc 以避免写竞争;提供 pick_out_cache_loc_slot 用于 post_forward 扰动选取刚写入的槽位。
  2. 新增四种扰动执行模块req_to_token.py 随机选取一个活跃条目并篡改其 req_to_token 值;real_kv_used.py 针对正在使用的物理槽位进行首字节翻转;real_kv_unused_cache.py 通过遍历 radix 缓存找到孤立槽位进行篡改,仅在 sweep 阶段生效;real_kv_post_forward.py 在 TAIL 内核之后选取 out_cache_loc 中的槽位进行翻转,利用 CUDA stream ordering 保证发生在 canary 哈希写入之后。
  3. 扩展 PerturbManager(manager.py):新增 req_to_token_pool 依赖;实现 perturb() 方法依次调用 req_to_token、real_kv_used、real_kv_unused_cache 扰动;新增 perturb_post_forward() 方法仅在 forward 后触发 real_kv_post_forward 扰动。
  4. 新增 PD 拆分端到端测试基础设施pd_fixture.py 创建 CanaryPDFixture,在单进程中同时启动 prefill 和 decode 两个引擎,使用多组 canary buffer;对应的测试文件(如 test_self_e2e_pd_perturb.py)在 prefill 侧启用扰动,验证 decode 侧检测到 real KV hash 违规而 prefill 侧保持干净。对每种扰动分别有 MHA 和 SWA 的测试参数化。
文件 模块 状态 重要度
python/sglang/srt/kv_canary/perturb/manager.py 扰动管理器 modified 8.33
python/sglang/srt/kv_canary/perturb/slot_picker.py 槽位选择器 added 8.54
python/sglang/srt/kv_canary/perturb/real_kv_unused_cache.py real KV 扰动 added 8.66
python/sglang/srt/kv_canary/perturb/real_kv_post_forward.py real KV 扰动 added 7.81
python/sglang/test/kv_canary/pd_fixture.py 测试夹具 added 7.66
test/registered/kv_canary/test_self_e2e_pd_perturb.py 端到端测试 added 7.56

关键符号

PerturbManager.perturb PerturbManager.perturb_post_forward PerturbManager.perturb_req_to_token PerturbManager.perturb_real_kv_used PerturbManager.perturb_real_kv_unused_cache PerturbManager.perturb_real_kv_post_forward slot_picker.collect_active_slots slot_picker.pick_out_cache_loc_slot real_kv_unused_cache.run real_kv_unused_cache._pick_sweep_slot_for_group real_kv_used.run real_kv_post_forward.run req_to_token.run

关键源码片段

python/sglang/srt/kv_canary/perturb/manager.py core-logic

核心调度入口,集成所有扰动模式的调用逻辑。

# manager.py — PerturbManager 核心调度逻辑
class PerturbManager:
    def __init__(self, *, config, req_to_token_pool, buffer_groups, outer_step_counter_getter, swa_window_size=0, sweep_interval=0):
        # 保存依赖:配置、req_to_token 池、buffer 组、步数获取器等
        self._config = config
        self._req_to_token_pool = req_to_token_pool
        self._buffer_groups = buffer_groups
        self._outer_step_counter_getter = outer_step_counter_getter
        self._swa_window_size = swa_window_size
        self._sweep_interval = sweep_interval
        self._radix_cache = None
        self._warmup_gate = WarmupGate(config=config, outer_step_counter_getter=outer_step_counter_getter)
​
    def attach_radix_cache(self, radix_cache):
        self._radix_cache = radix_cache
​
    def perturb(self, *, maybe_inaccurate_forward_batch):
        """在每次 forward 前调用,依次应用 req_to_token、real_kv_used、real_kv_unused_cache 扰动"""
        self.perturb_req_to_token(maybe_inaccurate_forward_batch)
        self.perturb_real_kv_used(maybe_inaccurate_forward_batch)
        self.perturb_real_kv_unused_cache(maybe_inaccurate_forward_batch)
​
    def perturb_post_forward(self, *, maybe_inaccurate_forward_batch):
        """在 forward 完成后调用,仅触发 real_kv_post_forward 扰动(在 TAIL 内核之后)"""
        self.perturb_real_kv_post_forward(maybe_inaccurate_forward_batch)
​
    # 各扰动的具体调度方法,分别委托给对应的 run 函数
    def perturb_req_to_token(self, maybe_inaccurate_forward_batch):
        req_to_token.run(maybe_inaccurate_forward_batch=maybe_inaccurate_forward_batch, config=self._config, req_to_token_pool=self._req_to_token_pool, warmup_gate=self._warmup_gate)
​
    def perturb_real_kv_used(self, maybe_inaccurate_forward_batch):
        real_kv_used.run(maybe_inaccurate_forward_batch=maybe_inaccurate_forward_batch, config=self._config, req_to_token_pool=self._req_to_token_pool, buffer_groups=self._buffer_groups, swa_window_size=self._swa_window_size, warmup_gate=self._warmup_gate)
​
    def perturb_real_kv_unused_cache(self, maybe_inaccurate_forward_batch):
        real_kv_unused_cache.run(maybe_inaccurate_forward_batch=maybe_inaccurate_forward_batch, config=self._config, buffer_groups=self._buffer_groups, radix_cache=self._radix_cache, swa_window_size=self._swa_window_size, sweep_interval=self._sweep_interval, outer_step_counter=self._outer_step_counter_getter(), warmup_gate=self._warmup_gate)
​
    def perturb_real_kv_post_forward(self, maybe_inaccurate_forward_batch):
        real_kv_post_forward.run(maybe_inaccurate_forward_batch=maybe_inaccurate_forward_batch, config=self._config, buffer_groups=self._buffer_groups, warmup_gate=self._warmup_gate)

评论区精华

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

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

风险与影响

所有扰动默认通过概率环境变量(默认 0)禁用,正常用户无影响。若启用,篡改真实 KV 数据可能触发 canary 检测,但若检测逻辑有缺陷(如哈希计算错误、指针映射失效)可能导致漏报或误报。real_kv_post_forward 依赖 stream ordering,若 GPU 调度异常可能导致竞争。PD 拆分测试涉及多进程,存在进程间同步和超时风险。

对最终用户透明,无行为变更。对系统增加了内建自测能力,有助于在生产环境或 CI 中提前暴露 KV 缓存一致性问题。对团队增加了测试覆盖,提高对 KV-canary 检测机制的信心。

默认禁用 核心路径变更 多进程测试稳定性

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论