推理与 KV Cache 05:从 Top-K 到数据就绪

作者:CherryYang 发布时间: 2026-11-12 阅读量:7 评论数:0

Top-K 确定了要访问的对象,运行时还需查明副本位置、等待数据就绪,并在使用期间保护其生命周期。本文串起驻留目录、加载状态、读放大和异步预取,说明稀疏选择如何转化为真实 I/O。NSA 机制来自公开资料;驻留目录与状态转换采用通用工程教学示意,不代表某个引擎已实现完整协议。


假设某层稀疏注意力选中了 Block 17、42、81。知道块号以后,可以马上让计算单元读取吗?还不行:17 可能已经在 HBM,42 只在外层,81 可能正在搬运。

稀疏选择改变了每步访问的数据量

对标准全注意力,单个 Decode 步骤需要考虑全部可见历史位置。固定模型维度时,历史 KV 的逻辑访问量随上下文长度 NN 近似线性增长。实际 HBM 事务量还会受内核分块、缓存、GQA 复用和并行策略影响。

NSA 把压缩表示、选中的较细粒度块、近期滑动窗口组织成不同分支。压缩分支提供全局信息,也为选择较细粒度块提供依据;窗口分支覆盖近期局部信息。论文中的分支输出通过学习到的门控组合。这里省略具体公式,重点看数据依赖。NSA 原论文给出了完整结构。

若每步最终选择 kk 个块、每块 qq 个 Token,窗口长度固定为 ww,则选中分支与窗口分支对应的数据规模约为:

Dselected+window≈kq sselected+w swindowD_{\mathrm{selected+window}}\approx kq\,s_{\mathrm{selected}}+w\,s_{\mathrm{window}}

两种 ss 分别表示对应分支、相同层与 Head 范围内的每 Token 字节量,未必相等。固定 k,q,wk,q,w 及模型维度后,这部分访问量对 NN 可以保持有界。

算法的选块大小也未必等于 KV 分配器的 Block Size。一个选中块可能覆盖多个物理页;选中的若是 Token,则还需先去重并映射到需要加载的页。

Top-K 给出对象,驻留目录给出位置

先把 17、42、81 当成某层/缓存组内的逻辑数据对象标识。真实系统还需带上请求或前缀、模型版本、层/组等命名空间,单个整数不足以全局唯一标识 KV。

下面是一张教学用的 Residency Directory:

对象 已有副本 HBM 状态 当前动作
17 HBM P7,外层副本可选 Ready 获取使用引用,直接读取
42 外层地址 A42 Absent 申请目标槽位,提交加载
81 外层地址 A81,目标 P9 Loading 复用在途任务,等待完成事件

Request Block Table 主要服务于“请求的逻辑位置映射到哪个可访问的缓存块”;驻留目录还要描述跨层级副本、在途任务和可用状态。实现可以将它们合并在同一套结构里,但职责仍需分清。

如果 Top-K 恰好输出了可直接用于某个设备池的 ID,也必须明确它属于哪个池以及有效期。对象身份与当前存放位置分开管理,才能在迁移后继续识别同一份数据。

把 Block 42 搬到 HBM,需要哪些状态

沿着 42 的路径,运行时先检查身份与版本,确认外层数据可恢复;随后为它申请 HBM 目标槽位,记录 Loading 状态和完成事件,再提交搬运。

搬运完成还不足以直接发布地址。如果需要解包、反量化或布局转换,应等这些操作以及必要的同步完成,再把目标标记为 Ready。Attention 消费者等待 Ready 事件后才能读取。

这里最容易出错的是并发使用:第二个请求发现 42 正在加载时,应在协议允许的条件下复用这次传输;读取者仍持有引用时,目标槽位不能被驱逐;传输失败后,也不能留下一个看似有效的目标映射。

同一次 Top-K,三种数据准备路径
17 · Ready

HBM 中已有可用副本

获取使用引用 → 读取 P7

42 · Absent

只有外层副本 A42

申请槽位 → 创建加载任务

81 · Loading

已在向目标 P9 搬运

复用在途任务 → 等待就绪

42 的恢复路径
  1. 确认身份与版本,申请 HBM 目标槽位。
  2. 进入 Loading,搬运数据;按需解包、反量化或转换布局。
  3. 完成必要同步,标记 Ready 并通知等待者。
  4. 持有使用引用期间读取;释放引用后才可能成为驱逐候选。

教学示意:传输完成不等于数据已就绪;失败时必须撤销不可用的目标映射。

HBM 命中率如何变成真实 I/O

如果等大的选中块中,有比例 hh 已在 HBM,则一个简化的跨层恢复估计为:

Drestore≈(1−h)DselectedD_{\mathrm{restore}}\approx(1-h)D_{\mathrm{selected}}

块大小不同时,应该使用字节命中率或逐块求和。实际传输还受在途复用、I/O 对齐、预取和副本表示影响。

取一个教学算例:某次选择覆盖 10 个等大的对象,每个 64 KiB,其中 7 个已在 HBM。另 3 个各读一次、无额外对齐与转换时,恢复量为 192 KiB。这里的 70% 只是算例参数,不是实测命中率。

再看 Token 选择:若每个被选 Token 的 KV 为 1 KiB,却分散在 10 个不同的 64 KiB 页中,而路径只能整页读取,那么需要 10 KiB 有效数据,却实际搬了 640 KiB。读放大为:

Aread=DtransferredDneeded=64A_{\mathrm{read}}=\frac{D_{\mathrm{transferred}}}{D_{\mathrm{needed}}}=64

如果多个 Token 落在同一页,去重和合并可以减少访问次数。因而分析稀疏卸载时,既要统计选中了多少 Token,也要看它们覆盖多少物理页、形成多少传输请求。

第三篇的跨层连续布局也是同一个问题:它有利于搬运完整跨层对象,但若不同层选择的块差异很大,整块取回可能增加无效字节。先确定真实消费粒度,再选择打包方式。

预取窗口从哪里来

当本步的块选择结果已知后,系统可以异步加载尚未驻留的数据,并执行不依赖这些数据的工作。如果窗口分支的数据已在 HBM 且调度依赖允许,它的计算可以构成一段重叠窗口。

设从加载发起到 Selected Attention 必须开始之间有 2 ms,而实际加载耗时为 5 ms,则至少暴露约 3 ms 等待。若加载只需 1.5 ms,并且没有资源争用和其他依赖,等待才有机会被完全隐藏。

还应测量重叠是否真的提高性能:DMA、HBM 写入、计算内核可能争用同一条路径。异步接口只说明提交不阻塞调用线程,无法保证数据一定及时到达,也无法保证计算期间没有降速。

介质与互联要分开选择

HBM、主机 DRAM、HBF 与 SSD 描述不同的数据承载层次;PCIe、UB 类互联和集群网络描述到达这些数据的路径。某种介质并不天然绑定某一种拓扑。

HBM 采用 DRAM 技术并靠近加速器,适合高带宽的活跃工作集。这里将“主机 DRAM”单独列出,是为了区分它与设备 HBM 的位置和访问路径。HBF 指 High Bandwidth Flash,采用 NAND 路线,目标是在容量与带宽之间提供另一种选择;它的访问粒度与时延仍需按具体实现测量。SK hynix 的公开技术说明介绍了这一方向。

路径视角 需要检查的内容
加速器本地内存 有效带宽、空间预算与计算访存争用
主机与设备之间,如 PCIe 路径 链路代际/宽度、NUMA、DMA 与中转复制
紧耦合资源域,如 UB 类互联 端点、路由、资源池化方式与跨设备访问成本
集群网络,如 RDMA 路径 远端服务、网络拥塞、传输粒度与尾时延

超节点可以理解为通过紧耦合互联形成较大资源域的一组设备,常服务于 Scale-up;Scale-out 则强调横向扩展到更多资源域或节点。它们的具体边界取决于系统架构。UB 是互联技术,不能简化成“HBF 到计算核的一根专用线”;其公开资料涵盖资源池化与更大规模组网,见 UnifiedBus。

所以,“全量 KV 一定用片上直连、稀疏 KV 一定用超节点、跨轮次 KV 一定用 SSD”只能作为特定假设下的候选方案。真正决定选择的是工作集、实际恢复字节、访问频率和时限,以及整条路径的有效能力。

把设计落实为可测的记录

对一次选择与恢复,至少留下这些记录,才能解释性能变化:

记录 用于区分
选中对象、去重后页数、实际搬运字节 算法稀疏性与读放大
HBM 字节命中率、在途复用量 已驻留数据与真正需要恢复的数据
选择完成、提交、就绪、消费时间 排队、传输与暴露等待
驻留容量、预取占用、被保护对象 快层空间是否被有效使用
TTFT、TPOT、吞吐与尾时延 局部优化是否兑现为服务收益

原先的“选出 17、42、81”由此成为一个完整问题:哪些数据已经可用,缺失部分以多大粒度穿过哪条路径,什么时候能安全交给 Attention。下一轮实验可以直接围绕这些可观测量展开。

上一篇:容量、带宽与时延,KV 卸载值不值得 · 回到起点:从一次生成理解 KV Cache 与容量。

评论