Prhub

#34096 config: the KV-cache configurator reads the bags

原始 PR 作者 ch-wan 合并时间 2026-08-10 05:45 文件变更 6 提交数 1 评论 9 代码增减 +99 / -61

执行摘要

KV 缓存配置器改读配置袋,统一 override 可见性

PR body 明确指出:"Reading them off the bags means seeing post-publish overrides, which the HiCache attach/detach endpoints and the memory-pool overrides actually produce"。此前 configurator 在构造 KV 池时读 self.server_args,看不到发布后覆盖,而 HiCache 动态挂载/卸载与内存池覆盖恰恰通过 post-publish override 生效,二者可能不一致。该 PR 是配置系统重构系列(reader-convergence,review vehicle #34087)的一部分,目标是把业务分支从直接读 raw ServerArgs 字段迁移到命名 runtime 层(flags / resources / 配置袋),让全局配置读取棘轮(read ratchet)归零。

值得精读。该 PR 是 SGLang 配置系统"读配置袋"迁移的一个典型样本:展示了如何在不改变公共 API 的前提下,把散落的 self.server_args 读取收敛到带命名 accessor 的配置袋层,并通过"同一解析值贯穿多个缓冲"保持一致性。值得关注的设计决策:max_draft_tokens 参数化让行余量与池缓冲共享一个解析值;draft worker 刻意读 process/target 袋值;pre_capture_activation_reserve_mb 保留实例读取的边界判断。配合 review 中作者对 draft/target 配置语义的解释(draft 实例 vs 进程记录),能深入理解这套配置架构的取舍。

讨论亮点

Review 由作者 ch-wan 通过 #34087 review vehicle 亲自完成,核心交锋如下:

  • suggestion(ch-wan,已修复)_handle_max_mamba_cache 仍读 server_args.max_speculative_num_draft_tokens,与三个已迁移兄弟点分叉。作者回复承认"on a draft configurator self.server_args is the draft instance while the accessor is the process record",不改会让 ReplaySSM ring 尺寸与相邻池不一致——最终改为 max_speculative_num_draft_tokens()

  • nit(ch-wan,已修复)_handle_max_mamba_cache 开头 server_args = self.server_args 成为死绑定,已删除并顺手把同方法内 guard 与赋值两次调用合并为一个局部变量。

  • P2(codex,头版已修复):HybridReqToTokenPool 的投机缓冲已用 live bag 值而 _build_req_to_token_pool 的行余量仍用启动实例,"near the model context limit, the page-aligned verify allocation can overrun into the neighboring request row"。最终 head 通过 max_draft_tokens=max_speculative_num_draft_tokens() 统一了两者。

    • P2(codex,未完全解决):DSV4 online MTP 从 live limit 分配 compress-state banks,但 DSV4PoolConfigurator 仍用 kvc.server_args 的旧启动值算预算(pool_configurator.py:639,779),"override from no draft tokens can fail the configurator's > 0 assertion";另一条指出 _handle_max_mamba_cache 非 ReplaySSM 分支仍用 get_spec().speculative_num_draft_tokens 而非 live maximum。这两条均落在变更文件之外,未见后续修复。
  • nit(ch-wan fresh re-review):PR/commit body 声称迁移了 dcp_size (four, the configured accessor),但该 diff 根本没有触碰 DCP sizing(base 上已用 live get_parallel().attn_dcp_size,也不存在 configured_dcp_size),属叙事夸大;建议收紧描述但 commit 未再更新。

实现拆解

按步骤拆解如下:

  1. allocation_sizing.py 引入解析后的上界参数get_alloc_len_per_decodeget_alloc_reserve_per_decodeget_req_to_token_extra_context_len 三个函数新增只读关键字参数 max_draft_tokens。调用方(KV-cache configurator)传入从配置袋解析出的投机 token 上界,函数内部以该值替代实例成员;默认仍回落实例自身字段,保证针对具体配置对象计量的调用方行为不变。核心收益:行余量(row headroom)与各投机缓冲共用一个解析值,post-publish override 后不可能相互背离。

  2. kv_cache_configurator.py 批量迁移实例读取到配置袋 accessor:包括 enable_mamba_extra_buffer / enable_mamba_extra_buffer_lazy 改为 mamba_extra_buffer_enabled() / mamba_extra_buffer_lazy_enabled()(clone_with_new_mamba、统一 mamba/SWA 池、混合 req 池、_calculate_mamba_ratio 共 8 处);max_speculative_num_draft_tokens 改为 max_speculative_num_draft_tokens()(混合 mamba decode 池、混合 req 池、DSV4 online MTP、_handle_max_mamba_cache 的 ReplaySSM record_len 共 3+ 处);ascend 后端检查从 self.server_args.attention_backend 改为 get_exec().kernel.attention_backend(3 处);_apply_token_constraints 的跨 PP all-reduce 判定改为 configured_pp_size() > 1_build_hybrid_req_pool 的 DFLASH/DSPARK 算法检测改为 get_spec().speculative_algorithmpre_capture_activation_reserve_mb() 按设计保留在实例上(其值是 target 的,且调用路径手头有实例)。

  3. runtime_context.py 文档与审计状态更新override_server_args 的 docstring 从 "Transitional — to be deprecated" 改为"这是测试获得已发布上下文的合规途径,且会保留"——因为 read ratchet 已将业务读取清零,但测试仍需一个已发布上下文投射配置袋;同时更新 tokenizer role 的 record-mode 审计记录(2026-08-06 文本模型跑出恰好 {"serving"},但 multimodal/LoRA/disagg/gRPC 形状未覆盖,故仍声明 full)。

  4. 测试配套联动test_dcp_layout_unit.py 删除注入 stand-in 的冗余字段(dcp_size 不在 stand-in 上,缩放来自 live get_parallel().attn_dcp_size);test_mamba_donated_alloc_ratio.py 从注入 lambda 方法改为发布 mamba_radix_cache_strategy(no_buffer / extra_buffer / extra_buffer_lazy)驱动被测路径,"一个输入形状"替代两个;test_global_config_read_ratchet.py 登记 kv_cache_configurator.py / configured_pp_size 新调用点及理由。

  5. 配置/部署配套:无新增 CLI 参数或 schema 变更;配置袋 publish 早于 configurator 构造的顺序由本系列既有机制保证(review 已确认 publish-before-configurator ordering safe)。

文件 模块 状态 重要度
python/sglang/srt/mem_cache/allocation_sizing.py 内存分配 modified 7.79
python/sglang/srt/mem_cache/kv_cache_configurator.py 缓存配置 modified 6.74
python/sglang/srt/runtime_context.py 运行时上下文 modified 5.47
test/registered/dcp/test_dcp_layout_unit.py DCP 测试 modified 5.08
test/registered/unit/mem_cache/test_mamba_donated_alloc_ratio.py 缓存测试 modified 5.03
test/registered/unit/test_global_config_read_ratchet.py 配置测试 modified 3.89

关键符号

get_alloc_len_per_decode get_alloc_reserve_per_decode get_req_to_token_extra_context_len _init_pools _build_req_to_token_pool _build_hybrid_mamba_decode_req_pool _build_hybrid_req_pool _build_dsv4_kv_pool _calculate_mamba_ratio _apply_token_constraints _handle_max_mamba_cache override_server_args

关键源码片段

python/sglang/srt/mem_cache/kv_cache_configurator.py core-logic

本次迁移的主战场:19 处 self.server_args 读取切换到配置袋 accessor,覆盖 mamba extra-buffer 谓词、投机预算、pp_size、投机算法与 ascend 后端检查,并修复 _handle_max_mamba_cache 的漏迁移。

    def _build_req_to_token_pool(self, *, max_num_reqs: int) -> ReqToTokenPool:
        # 行余量与下方各内存池使用同一个从配置袋解析出的 draft token 上界,
        # 保证 post-publish override 之后两者不可能不一致。
        extra_max_context_len = get_req_to_token_extra_context_len(
            self.server_args,
            max_draft_tokens=max_speculative_num_draft_tokens(),
        )
​
        if get_disagg().disaggregation_mode == "decode":
            # decode 池需要为预分配请求额外预留槽位
            pre_alloc_size = get_disagg().disaggregation_decode_extra_slots
            if self.mambaish_config:
                req_to_token_pool = self._build_hybrid_mamba_decode_req_pool(
                    max_num_reqs=max_num_reqs,
                    extra_max_context_len=extra_max_context_len,
                    pre_alloc_size=pre_alloc_size,
                )
            else:
                req_to_token_pool = self._build_decode_req_pool(
                    max_num_reqs=max_num_reqs,
                    extra_max_context_len=extra_max_context_len,
                    pre_alloc_size=pre_alloc_size,
                )
        elif self.mambaish_config:
            req_to_token_pool = self._build_hybrid_req_pool(
                max_num_reqs=max_num_reqs,
                extra_max_context_len=extra_max_context_len,
            )
        else:
            req_to_token_pool = self._build_default_req_pool(
                max_num_reqs=max_num_reqs,
                extra_max_context_len=extra_max_context_len,
            )
        return req_to_token_pool
    # 说明:本方法中的 get_disagg() / 配置袋 accessor(max_speculative_num_draft_tokens)
    # 都读取已发布上下文,能看到 HiCache attach/detach 与内存池 override 产生的
    # post-publish 覆盖;而 self.server_args 仍用于取实例自身属性(如 topk、页大小)。

评论区精华

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

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

风险与影响

  1. 内存预算不一致(中风险,部分未解决):codex 指出的两条 P2 未完全闭环——DSV4 online C128 MTP 的 DSV4PoolConfigurator 预算仍基于 stale startup limit(pool_configurator.py),post-publish override 提高投机 token 数后可能出现分配期 OOM 或断言失败;_handle_max_mamba_cache 非 ReplaySSM 分支的 mamba scratch 预算仍用当前 speculative_num_draft_tokens 而非 live maximum,自适应配置提升候选步数时可能少算 KV 内存。两者都只在 override 场景触发,默认路径不受影响。
  2. draft/target 配置分叉(已修复但有残留观察面)_handle_max_mamba_cache 迁移后 draft configurator 统一读进程级 record,行为正确性依赖 publish 顺序;review 确认 ordering safe,但若未来在 publish 之前构造 configurator 会读到旧值。
  3. 测试语义变化:mamba 比率测试从注入 lambda 改为发布 strategy 字符串,对 mamba_extra_buffer_enabled() 与 strategy 映射的耦合更强,若映射未来变化测试可能失真;反之测试策略映射经 review 确认正确。
  4. 回归面allocation_sizing 默认回落实例成员,普通调用方无行为变化;但 _calculate_mamba_ratio 断言路径(lazy 需要 overlap)现在依赖袋值,与 env override 组合时需注意断言触发顺序。

影响范围集中在 SRT 内存池构造与配置读取架构:

  • 用户/运维:无 API 变化。间接收益是 HiCache 动态 attach/detach 与内存池 override 在配置器读取侧变得一致,避免 KV 池尺寸与行余量在覆盖后互相矛盾;这在未来动态扩缩容/热更新场景是正确性前提。
  • 系统:投机解码(EAGLE/DSV4 online MTP/ReplaySSM)、Mamba/混合线性池、DCP/PP 容量计算等路径的配置输入统一来自配置袋 accessor,read-ratchet 测试(test_global_config_read_ratchet)从 7 个调用点增至 8 个,业务代码直读 raw 字段进一步清零。
  • 团队:属于配置系统重构系列的中段推进(#34087 reviewer-convergence、#34133 DCP 拓扑派生同系列),为后续 tokenizer role namespace 收窄和 override 机制定稿铺路;同时 PR 体描述对 dcp_size 的夸大提示合并前需核对 commit 叙事与实现。
post-publish override 下内存预算可能不一致 DSV4 online MTP 预算仍用启动时旧值 Mamba scratch 预算未用 live maximum draft 与 target 配置读取依赖 publish 顺序 PR 描述与实现不符

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论