Memory 技术日报 2026-08-07:从 chunk 调度到页预算,KV 状态的四个正确性修补

Memory 技术日报 2026-08-07:从 chunk 调度到页预算,KV 状态的四个正确性修补

本期拆解 vLLM 与 SGLang 在 MLA chunk 调度、disaggregated radix cache、paged SWA 物理页预算和 packed KV 清零范围上的四个窗口内修补,并给出复现入口与未验证边界。

今天入选的四个窗口内提交,解决的不是「模型又变聪明了」,而是上下文和缓存系统里更容易被忽略的四类边界:请求如何切 chunk、共享前缀如何跨 staging grid 传输、滑窗缓存如何按物理页计费,以及 packed KV block 如何只清零自己的物理范围。它们共同指向一个判断:在 memory/context 系统里,先把状态的物理归属和完成条件写清楚,再谈吞吐或复用率。
时间口径是 2026 年 8 月 6 日 09:00 至 8 月 7 日 09:00(北京时间);以下时间均为 GitHub commit 时间换算后的北京时间。四条均来自窗口内的 GitHub commit,证据等级是「代码变更 + 仓库测试」,不等于已经经过独立线上 benchmark。

1. vLLM:MLA chunked context 改成按请求排程

变化是什么
vLLM 在 commit b38e111d 中把 MLA(Multi-head Latent Attention)chunked context 的处理,从按统一 chunk 切分改为按 request 组织的 ContextChunk / _ContextChunkPlan。这意味着一个 batch 里,不同请求的 context 片段可以被单独规划、累积和重组;无 context 的 prefill 则通过 empty_token_slices 跳过,而不是继续依赖 mask_empty_context。提交时间是 8 月 7 日 00:45,改动涉及 mla_attention.py、sparse MLA、prefill backend 以及 Kimi K3 的 MLA 路径。1
这次改动还把 reorg_kvcache 从依赖 chunk_size/chunk_idx 改成使用每个 chunk 的 local_starts,并把 chunked-prefill workspace 的下限与 cache block size 对齐。新增测试覆盖了「每个 context row 只收集一次」「continuation 只能发生在 chunk 的第一个 request」「tail splitting 尽量减少 chunk 数」「无 context prefill 被跳过」以及 DCP 下的 local chunk 预算。测试文件同时加入了 DeepSeek-R1、TP=16、auto/fp8 KV cache、workspace size=1024 的后端一致性场景,并以 SDPA reference 做对照。2
先复现什么
如果你维护 MLA 或长上下文 serving,先复现 chunk planner 的不变量,而不是先跑端到端吞吐:
  1. 用混合 batch 同时放入长 context、短 continuation 和无 context prefill,检查每个 row 是否恰好进入一次 chunk。
  2. 固定 DeepSeek-R1、TP=16、autofp8 两种 KV cache dtype,运行新的 chunked-context correctness 测试,观察 backend 输出是否仍与 SDPA reference 一致。
  3. 再切换 DCP,检查 local chunk 预算、KV 重组位置和 tail splitting 是否仍保持一致。
不能从中推出什么
这不是一个「MLA 端到端吞吐提升」的 benchmark,也没有在 commit payload 中给出独立 CI 结果。它首先修正的是 chunk 规划和输出合并的正确性;workspace 下限、测试中的 TP=16 或 DeepSeek-R1,不能直接外推到你的模型、并行度或线上 batch。

2. SGLang:radix cache 进入 disaggregated staging buffer

变化是什么
SGLang 在 commit 05c7ebf 中让 staging buffer 支持 radix cache,并处理 prefill TP 与 decode TP 不一致时的 KV 分片传输和 scatter。prefill 侧新增 disagg_decode_prefix_lenearly_send_prefix_end,首次 batch 会快照 early-send 的 prefix 边界;非最后 chunk 则按 staging grid 对齐并拆成多个 segment。decode 侧改用绝对 token offset:prefix_tokens + page_start * page_size,收齐 writer 后再触发 scatter。提交时间是 8 月 6 日 23:59。3
完成条件也被收紧:每个 chunk 都要发 staging-ready 通知,Success 之后若仍有 outstanding chunk,room 继续保持 Transferring;只有 outstanding 归零、事件完成且 room 已 concluded 才 teardown。若 decode prefix 不是 page 对齐,代码会把 room 标记为 failed;如果 all-ranks 已成功但 chunk 迟迟不到,则受 SGLANG_DISAGGREGATION_WAITING_TIMEOUT 约束。新增集成测试使用 prefill TP=4、decode TP=2、staging+radix cache、chunked-prefill-size=256 和 GSM8K few-shot,断言得分大于 0.60。这个分数是该测试的通过门槛,不是独立性能结论。4
先复现什么
如果你的系统把 prefill 和 decode 拆到不同进程或节点,建议按以下顺序复现:
  1. 固定 prefill TP=4、decode TP=2,开启 staging 与 radix cache,把共享 prefix 刻意切过多个 staging grid slot。
  2. 记录每个 chunk 的发送、writer 收齐、scatter、transfer 完成和 room teardown 时间点;不要只看最终请求是否返回。
  3. 单独构造非 page-aligned decode prefix 和 delayed chunk,验证系统是明确失败或等待,而不是提前把 room 当作完成。
不能从中推出什么
这次提交证明的是 staging/radix cache 在特定 disaggregation 配置下的边界处理更完整,不等于所有 TP 组合、网络拥塞和 page size 都已覆盖。GSM8K 大于 0.60 是回归测试门槛,不能被写成 radix cache 带来的质量或吞吐提升。

3. SGLang:paged SWA 恢复请求改用物理页预算

变化是什么
SGLang 在 commit af7c62e 中修正 paged SWA(sliding-window attention)请求从 retracted queue 恢复时的预算计算。_prealloc_required_tokens 现在读取 allocator 的 page_size,在 page_size > 1 时把 full pool 和 SWA pool 的需求都向上对齐;SWA 的扣减则直接使用对齐后的需求,因为该 pool 没有 radix-cache eviction。提交时间是 8 月 7 日 07:32。5
新增单测把 page_size 设为 128、fill_len 设为 574、可用物理预算设为 18 页,并模拟 4 个被 retracted 的请求;结果只能恢复 3 个,剩余请求留在队列,_pre_alloc 被调用 3 次,剩余预算为 3 页。这个例子把「逻辑 token 数」和「allocator 实际按整页收取的物理预算」分开了。6
先复现什么
  1. 用非 page-aligned 的输入长度,例如测试中的 574 token,分别设置 page_size=1、128 和你线上实际值。
  2. 让多个 retracted request 竞争同一组 full/SWA pool,逐个记录逻辑需求、向上对齐后的物理需求、恢复顺序和剩余预算。
  3. 对照开启/关闭 radix cache、不同 sliding-window size 的路径,确认预算扣减不会出现「逻辑上放得下、物理页上放不下」的恢复结果。
不能从中推出什么
这个修复只说明恢复队列的物理页核算与 allocator 更一致;它没有给出更高吞吐、更高 cache hit rate 或更长上下文的测量。测试还明确依赖 SWA tail prealloc、关闭 radix cache 和固定的物理预算模拟,不能替代真实 GPU 压力测试。

4. vLLM:packed KV block 清零不再假设连续 stride

变化是什么
vLLM 的 commit d6af803 修复 packed KV block 的 zeroing stride。此前清零偏移按 block_id * page_size 推算;现在把「物理 block 起点」与「本次清零的 page span」拆开,kernel 使用独立的 seg_block_strides_ptrKVBlockZeroer 也保存每个 segment 的地址、block stride 和 page size,从而在多 KV cache group 或 packed segment 中只清零目标 block 的对应 page。提交时间是 8 月 7 日 04:49。7
新增测试 test_packed_segment_zeros_only_its_last_block_page,验证 packed KV segment 按 block stride 定位时,不会误清零相邻内存。实现同时增加了对 block size、kernel block size、地址和页大小 4 字节对齐的断言;测试路径需要 CUDA,Mamba 层则跳过。8
先复现什么
如果你有 packed KV、多个 KV cache group 或自定义 block layout,先做破坏性隔离测试:在相邻 segment 写入不同哨兵值,只执行一个 segment 的最后一页清零,再确认相邻 segment 和同 segment 其他 page 都保持不变。随后覆盖不同 block stride、page size 和 warmup 的 n_blocks specialization。
不能从中推出什么
这是物理内存清零范围的正确性修复,不是 KV 容量增加,也没有给出 kernel latency 或显存节省数字。它还受 CUDA、对齐约束和 AttentionSpec 路径限制;不能据此断言 Mamba 或所有 cache backend 都获得同样修复。

放在一起看

进展解决的状态边界证据与可复现入口仍未验证
vLLM MLA chunked contextrequest 级 chunk 规划、空 context 和 KV 重组commit + chunk planner / backend correctness 测试;见 1端到端吞吐、其他模型与并行配置
SGLang staging + radix cachegrid segment、绝对 scatter offset、outstanding chunk 完成条件commit + TP4/TP2 集成测试;见 3网络抖动、更多 TP 组合、超时策略的线上代价
SGLang paged SWA逻辑 token 到物理页预算的对齐commit + page_size=128 单测;见 5真实 allocator 压力、吞吐与恢复延迟
vLLM packed KV zeroingsegment stride 与 page span 解耦,避免越界清零commit + CUDA 单测;见 7不同 backend / Mamba 路径、kernel 性能

结论

这四条进展可以按「状态从哪里来、占多少物理空间、何时算完成、哪些内存绝不能碰」来读:MLA 先把 context 切分从 batch 级假设收回到 request 级;SGLang staging 把传输完成从「收到 Success」收紧为「所有 chunk 和事件都完成」;paged SWA 把恢复预算对齐到 allocator 的物理页;packed KV 则把 segment 的 stride 与清零 span 分开。它们值得跟进的共同原因,不是已经证明了某个系统更快,而是让下一轮 benchmark 的变量边界更可控。
大模型 Memory 技术日报

大模型 Memory 技术日报

追踪大模型 memory 技术前沿,涵盖长上下文、KV 缓存、RAG、外部记忆等方向,每日更新结构化文章。

This story was produced automatically by a channel. One sentence is all it takes for Neodrop to keep producing for you.

Related content

  • Sign in to comment.