首页优化地图方法索引基础概念
返回技术汇总表 ↗

M005 · 独立详解

KV Cache 量化与压缩:长上下文怎样用更少空间保存历史

顺着“生成 K/V → 压缩写入 → 读取 Attention”解释缓存量化,计算容量和误差,并区分分页、卸载、裁剪等相邻方法。

模型与算法内存与数据搬运算子与编译详解已编写
视频讲解待制作

这篇文章的小视频尚未制作;可以先阅读下方文字详解。

本页目录

01 · 权重固定,KV 却随上下文和请求数增长

历史 KV 复用免去了重复计算,却需要为每个有效位置保留各层的 K/V。提示词越长、输出越长、并发请求越多,缓存压力通常越大。即使权重已经量化,KV 也可能仍是 BF16;给权重换格式不会自动改变缓存。

量化缓存的目标是把每个历史元素的表示缩小。缓存受限时,这可能让同一设备容纳更多有效位置或请求;读取带宽受限时,更小的表示也可能减少流量,但还需要算上还原和内核适配。

假定普通 K/V 结构单请求有效数据容量
32层、8个KV头、头维128、4096位置、16位2×32×8×128×4096×2 = 512 MiB
相同元素改为8位256 MiB,不含尺度等元数据
相同元素理想打包为4位128 MiB,不含尺度等元数据

02 · 沿数据路径找量化发生的位置

  • 产生:当前输入经过每层计算,得到本层新的 K 和 V,按实现约定完成位置编码等处理。
  • 写入:确定尺度,把新 K/V 变成低比特表示;把整数/低位浮点码与必要的尺度、边界信息一起保存。
  • 读取:新 Q 读取历史的压缩 K/V。Attention 后端把其还原成合适的计算输入,或直接走支持的低精度路径。
  • 追加与管理:继续维护有效长度、分页地址、共享前缀和尺度生命周期,不能只知道数据 dtype。
教学伪代码 · 展示机制,不是可直接部署的引擎接口
# 每层每次处理新增位置,概念性顺序
q, k_new, v_new = layer_project(current_hidden)
q, k_new = apply_position_encoding_if_required(q, k_new, positions)
k_codes, k_meta = encode(k_new, cache_recipe)
v_codes, v_meta = encode(v_new, cache_recipe)
cache.append(k_codes, v_codes, k_meta, v_meta)
output = attention_backend(q, cache, correct_causal_visibility)

scale 的生命周期尤其重要。如果旧整数码按 s=0.1 编码,却仅因为新值变大就把整段缓存的全局 scale 改为0.2,旧元素会被错误地放大两倍。必须保持旧块的尺度,或按正确转换规则重新编码旧内容;动态缩放不等于随便覆盖一个标量。

03 · K 的误差和 V 的误差,影响位置不同

Attention 中,K 先参与 QKᵀ 产生分数,再经过 Softmax 决定各历史位置的权重;V 则在这些权重确定后被汇总。所以 K 的近似可能改变“看谁”,V 的近似可能改变“读到什么”。二者不一定使用相同粒度或尺度。

只量化 K 的手算例子 · 小模型教学,不代表实际长上下文误差
一个单查询、标量 V 的教学例子:
Q = 1,K=[0.14,0.26],V=[1,3],不额外缩放
原分数=[0.14,0.26],Softmax≈[0.47004,0.52996]
原输出≈2.05993

若 K 用整数格点 s=0.2 量化:K_hat=[0.2,0.2]
两项分数相同,权重变为[0.5,0.5]
保持 V 不变,输出=2.0

如果固定权重 [0.5,0.5],V=[1.0,2.8] 用 s=0.5 就近舍入后成为 [1.0,3.0],输出则从1.9变为2.0。这是另一个只看 V 的例子。真实模型同时含多维 K/V、位置编码和后续层,不能把单步误差直接当作最终任务质量损失。

04 · 格式、粒度与近期缓存,是三个不同选择

选择要回答的问题可能的代价
整数 / 浮点位数保存 INT8、FP8、低位整数或其他编码?误差与硬件支持不同,8位不是一个统一格式。
量化粒度每层、每头、每 token、每通道还是每块共享尺度?粒度细可改善表示,但增加元数据和计算。
近期高精度区是否暂时保留最近一段,再成组压缩旧内容?避免每步碎片转换,却增加常驻高精度容量和管理。
敏感层例外哪些层或头继续保存原精度?改善质量,但降低总体压缩比例。

KIVI 的论文根据其观测选择 K 的 per-channel 与 V 的 per-token 量化,并提出低位 KV 方案。其具体分组和近期高精度缓存设计是一种方法路径,不能推广为所有模型必须如此,也不能把2位研究方案与 FP8 引擎选项当作同一实现。

依据:KIVI · A Tuning-Free Asymmetric 2bit Quantization for KV Cache ↗

研究级更低位方案常需要专用编码、残差或离群值处理和专用内核。方法在论文中成立,不代表当前使用的通用推理后端已经支持该格式。

05 · 加上元数据后,还剩多少容量收益

回到512 MiB 的16位基线,共有268,435,456个 K/V 标量。假设只对低位区域每128个标量存一个 FP16 scale,没有零点或其他元数据。8位码256 MiB加尺度4 MiB,共260 MiB;4位码128 MiB加尺度4 MiB,共132 MiB。

把元数据也算上:有效 KV 到底占多少

32层、8个KV头、头维128、4096位置、单请求。低位区每128个标量存一个2字节尺度;无零点、近期高精度区、对齐、块表与工作区。不模拟具体 FP8 或 INT4 内核。

这是完整缓存统一格式的简化估算。如果最近128个位置仍保留16位,其他3968个位置用4位:近期数据16 MiB,旧数据124 MiB,码的总量已是140 MiB,再加旧区尺度等开销。不能继续拿128 MiB作为总量。

也不能把全缓存容量当作每步实际 HBM 读取量:Attention 后端的分块、共享、窗口与并行切分会影响流量。容量公式适合预算,带宽与延迟需要 profiling。

06 · 缓存小了,Attention 就一定快吗

读取路径怎样执行检查什么
先还原完整历史到 HBM低位缓存 → 完整高精度临时表 → 普通 Attention展开后的工作区和写回可能抵消部分收益。
分块读取并在内核内还原读压缩块与尺度 → 局部解码 → 计算需要融合读取/解码的后端,解码仍消耗资源。
原生或专用低精度 Attention对 Q/K/V 按支持配方执行低精度运算不只是缓存格式;查询量化与数值配方可能一起变化。

vLLM 的 FP8 KV 文档说明,一些后端除了存储低位 K/V,还会让 Attention 使用低精度输入,包括量化 Q。实际走哪种路径需按后端、模型、头维与版本确认;不能把“FP8 KV”一律解释为“只存得小,计算完全不变”。

依据:vLLM · Quantized KV Cache(latest) ↗

可能的收益包括:减少缓存占用、降低某些路径的读取量、允许更大并发。可能的代价包括:确定尺度、写入转换、解码、元数据读取与工作区。相同并发和更大并发应分别测量,才能区分单请求变快与容量释放带来的整体吞吐提升。

07 · 与其他 KV 优化怎样区分、怎样组合

方法主要改变是否减少保留的位置
历史 KV 复用保存历史结果,避免重算通常保留仍需使用的历史。
分页 KV分配、逻辑到物理地址映射本身不删除有效历史。
前缀缓存跨请求复用兼容起始部分共享相同结果,不是裁剪输入。
KV 量化每个元素的近似表示通常保留位置,但数值近似。
卸载 / 分层缓存把缓存放到其他存储并按需取回未必删除,但增加传输与等待。
淘汰、稀疏选择、滑动窗口选择仍允许访问的历史范围可能减少可见位置;需区分模型原生语义与额外近似策略。

总览里的“量化与压缩”是一个方法族入口。这篇先详解降低元素位数;位置裁剪、稀疏选择与跨层结构压缩各有自己的数学条件,不能由量化公式证明正确。M017 等关联入口进一步区分这些方向。

组合前缀共享时,还需让双方认同尺度和缓存格式;不能只有 token 前缀相同,就把不同编码缓存直接解释为当前格式。分页则需要让低位数据和元数据一起被正确寻址。

08 · 先验证一个 Attention,再接服务后端

下方 CPU 例子比较原始 Attention、只量化 K、只量化 V、两者都量化的输出;同时用8位码验证“改了旧数据的 scale 却不重新编码”会改变还原值。它实现的是均匀对称整数教学方案,不模拟 FP8、KIVI 或实际 Attention 内核。

教学伪代码 · 展示机制,不是可直接部署的引擎接口
reference = run_fixed_tokens(cache_dtype=original_dtype)
recipe = choose(cache_format, k_granularity, v_granularity, scales, exclusions)
compressed = run_same_tokens_with_compatible_backend(recipe)
compare_logits(reference, compressed, tolerance_and_task_requirements)
measure(valid_cache_bytes, metadata_bytes, peak_memory, decode_time)
# 再固定并发测延迟,以及固定显存预算测可服务并发/吞吐

vLLM 的官方 FP8 KV 文档提供缓存格式、尺度校准、粒度和层例外的实现入口。部署时分别记录“权重量化配置”和“KV 配置”,并检查导出尺度是否被实际读取;默认尺度不是完成了代表性校准的证明。不要假设所有粒度组合都被所有后端支持。

依据:vLLM · Quantized KV Cache(latest) ↗

09 · NVIDIA 与昇腾的实现入口及验证边界

NVIDIA 路径可查 TensorRT-LLM 的缓存与数值精度文档、vLLM 的 FP8 KV 配方。昇腾的 ModelSlim 26.0.0 有 INT8 KVCache 说明,描述 key_states/value_states 的校准与伪量化;文档也明确其伪量化阶段仍需原精度内存,真实节省需要底层算子支持。工具可以模拟误差,不等于运行时缓存已经按 INT8 存放;推理引擎的消费格式与内核要继续核对。

依据:TensorRT-LLM · KV Cache System ↗ · TensorRT-LLM · Numerical Precision ↗ · ModelSlim 26.0.0 · KVCache INT8 量化算法说明 ↗

  • 使用相同原始模型和 token 输入,观察各层误差、最终 logits 与任务质量。
  • 覆盖短/长上下文、检索与复制任务、领域输入、长输出及位置边界;不要只测一般短问答。
  • 测试缓存追加、分页边界、前缀共享、并行切分与模型支持的组合。
  • 分别测相同并发延迟与相同容量下的吞吐,并记录格式、尺度来源、内核和工作区。

缓存成为容量或带宽瓶颈时更值得尝试;短上下文、计算或通信占主要时间、或量化内核不适配时,收益可能有限甚至变慢。本文给出机制与教学验证,不提供未经硬件实测的两家性能排名。

10 · 用四个问题检验理解

  • 权重已经 INT4,为什么 KV 仍可能是 BF16?
  • 为何 K 与 V 的量化误差影响不同环节?
  • 低位码没变,为什么改 scale 会把旧数据读错?
  • 缓存容量减半,为什么单 token 生成时间未必减半?

流程位置与关联方法

这个方法可能出现在多个位置;计算线包含模型计算与算子实现,执行线包含运行时、内存和通信。

资料与核查范围

原理依据以原始论文和官方文档为主;算例与时间线是教学推导。文档核查日期:2026-10-08。引用 main / latest 文档时,实际接口以安装版本为准。

代码为接入片段或教学伪代码;本页没有声称完成 NVIDIA / 昇腾硬件实测。

← 返回总表中的 M005继续阅读:矩阵乘法与访存优化 →
AI Infra 知识库 · 总览 → 独立讲解网站更新 2026-10-08
搜索知识库

搜索方法与基础概念 · Esc 关闭