学习 / 实践

KV 缓存开销剖析:把省下的计算和新增的工作分开

llm / 理解 · 机制拆解

对909次查询做分段计时,验证源码签名、查找、复制与续算分别花在哪里,同时保留缓存仍慢的结果。

进阶 · 9 分钟 · 更新于 2026-10-07 · 步骤 12 / 18

浏览统计暂不可用

本文目录 6
跳到正文 ↓

固定版本代码 · 原始证据 · 实验档案

上一轮缓存准入实验出现了一个不太好看的结果:少投影一些Token,查询却更慢。那时日志只记录总耗时,不能直接把原因归咎于“Python慢”或“复制太多”。本篇做一个更窄的实验:先固定为永远命中的八Token前缀,再把续算链分段计时。

这是未训练的两层NumPy教学Decoder,维度16、完整输入12Token。没有GPU、真实模型调用或模型质量评价。它回答本机这段实现的开销问题,不代表所有KV缓存。

对照组究竟改了什么

路径 签名方式 计算
full 不需要缓存签名 重算12Token,取后4个输出
rehash 每次读源码、哈希权重和配置 查找八Token缓存,再续算4Token
frozen 模型初始化时固定签名 相同查找、复制和续算

缓存键仍包含 scope、签名和前缀Token。冻结模型将embedding和权重设为只读;换权重应创建新实例及签名。这是可信本地代码的生命周期约定,不是防御恶意修改的安全边界,也不允许热改权重后继续使用旧缓存。

总查询 = 签名 + 查找 + 复制 + 续算 + 未归属开销
                    ↑
       少算Token,并不能消除左边三项

怎样量,避免把一次波动当结论

三个固定种子,每种路径先预热五次;之后每种子101轮,每轮随机交错三路径,共909次正式查询。用单线程BLAS环境,计时采用 perf_counter_ns。返回值与完整重算结果比较,最大容差1e-12。

记录包含 total、signature、lookup、copy、compute 和 residual。residual不是“其它硬件瓶颈”的测量,只是总时长减去已包围片段的差,包括计时调用、字典操作和片段之间的程序工作。

本机结果:改好了一部分,但还没有胜过重算

下表各列是该片段独立中位数,单位微秒,不能把各列中位数相加当作总时长中位数。

路径 总查询 签名 查找 复制 计算
full 252.7 — — — 250.9
rehash 682.7 365.2 2.8 12.0 290.4
frozen 273.6 0.6 2.2 9.0 257.1

在这个永远命中的小工作负载里,避免每次计算源码/权重签名明显缩短了查询。但frozen中位数仍比full多20.9微秒。数组较小、调用与分段计算成本仍存在;本轮没有继续分解NumPy内部开销,因此不能给出更细的确定归因。

这也不是上一轮4860次请求结果的“更正”:上一轮含冷启动、工作集和淘汰,本轮故意排除了它们。两者的分母和测量边界不同,不应直接拼成加速图。

读代码时注意所有权

命中后仍复制缓存数组,再传给续算。若直接把公共缓存作为可变工作区,某次续算可能污染下一个请求;性能优化不能以隐式共享写入换取。是否可以安全地减少复制,需要明确数组是否只读、层内是否分配新数组,并增加跨请求隔离验证,本轮没有擅自省掉。

小练习

从profile.json任选一行,验证各段加residual恰好等于total;再对整列分别求中位数,观察“中位数的和”和“和的中位数”通常不相同。然后增大输入长度,在新目录重新运行;不要预写“长序列一定更快”,先检查当前固定前缀长度是否仍合理。

若不同机器数值变化,先检查NumPy/BLAS版本、线程环境、后台负载与计时范围。若结果不等价,先检查模型身份和绝对位置,不应先讨论速度。下一篇研究不保存完整注意力分数矩阵,换一个内存问题。

从干净目录复现

使用 Python 3.12。入口一次运行这组三个主题的对照,各篇只解读自己的子集,不把同一份记录重复当作新增回合。

git clone https://github.com/VirtualSelect/hohoo-ai-lab.git hohoo-ai-lab-study
cd hohoo-ai-lab-study
git checkout 02a2660e22c969e70e3a6f095003614a7dfa448e
python -m pip install numpy==2.2.6
python experiments/10-attention-costs/run.py --out outputs/my-run
python experiments/10-attention-costs/audit.py outputs/my-run

输出目录必须不存在。本机验证环境为 Windows,Linux/macOS尚未复测。不需要模型密钥或付费服务。manifest中的代码冻结提交早于上方含证据的归档提交,源码哈希对应实际执行文件。

写给未来的自己合上文章前,留下一点自己的理解。

你的私人学习便签,只存在当前浏览器,不会上传或公开。清理浏览器数据会丢失,请导出留存。三种语言共用这篇文章的便签。

下一篇已发布内容:注意力分块:不保存完整分数矩阵,如何保持结果? →

当前学习位置

理解 / LLM

  1. ○ 24次全对之后:怎样设计更有区分度的上下文实验?
  2. ○ KV 缓存开销剖析:把省下的计算和新增的工作分开
  3. ○ 注意力分块:不保存完整分数矩阵,如何保持结果?

继续探索

继续探索

  1. 实验 / 033

    KV 缓存开销剖析:把省下的计算和新增的工作分开

    对909次查询做分段计时,验证源码签名、查找、复制与续算分别花在哪里,同时保留缓存仍慢的结果。

    已完成
  2. 项目 / 002

    Java LLM 实践集

    Java 会话、请求重试与持久化边界,以及注意力、缓存成本和量化误差的可复现实验。

    构建中
  3. 机制拆解

    LLM 机制实验(七):缓存省了计算,为什么实测反而更慢?

    4860次实测查询比较三种缓存准入策略,把字节预算、工作集、计算量与本地耗时放在一起验证。

    12 分钟已发布

接下来,走哪条路?

依据文章关联与同主题已发布内容整理,不使用随机推荐。

← 全部文章