【随笔】KV缓存量化:省下的显存,要付出多少数值误差

上一篇把KV缓存移到CPU内存,分析了逐层预取的传输等待。还有一条节省容量的路线,把每个缓存元素保存得更紧凑。问题随之变成,节省了多少字节,恢复数值要做多少工作,最终生成结果会受多大影响?

一、KV缓存里哪些数据可以缩小

自回归生成会不断积累注意力层的键和值。KV缓存量化用较低位宽保存其中的数值,并保留恢复数值所需的比例等信息。注意力计算需要用到这些历史状态,因此读取时要按实现进行解码或反量化。

本篇用Transformers 4.57.1的quantized缓存接口说明配置方式。其文档列出的后端包括Quanto和HQQ,支持位宽与量化轴选择各有要求。下面的机制实验使用独立Python代码,便于把舍入和分组的影响逐项算出来。Transformers缓存量化文档

栗子把一组原始数值转换成短整数,小橘根据同组的缩放系数恢复近似数值。保存整数时还要带上刻度,恢复后的数值才有意义。

二、先算容量,再看比例信息

假设全注意力模型有32层、8个KV头、头维度128,单请求保留8192个Token。K和V各一份,每个元素以16位保存。

text 复制代码
元素个数 = 2 × 32 × 8 × 128 × 8192
16位原始载荷 = 元素个数 × 2字节 = 1 GiB
4位紧凑载荷 = 元素个数 × 0.5字节 = 256 MiB

这两行计算只比较数值载荷。实际还要加上每组的缩放参数、零点或其他元数据,以及高精度残留区、对齐与临时工作区。

以每64个元素一组、每组单独保存一个4字节缩放系数为例,4位载荷需要32字节,再加4字节,合计36字节。对应的16位载荷为128字节,这个简化格式节约71.875%的空间。把256MiB直接当成整个进程的显存峰值,就遗漏了模型权重和这些额外开销。

三、离群值为什么会影响普通数值

先采用一个便于手算的对称整数编码。4位编码使用-7到7的整数级别,比例为该组最大绝对值除以7。对每个数执行除比例、舍入、裁剪,恢复时再乘回比例。

对于[0.1, 0.2, 0.3, 7.0],比例是1。前三个数都舍入成0,最后一个数能准确恢复。保存7.0的范围占用了整个刻度,小数值的差异被压平了。

如果改成[0.1, 0.2, 0.3]和[7.0]两组,各组使用自己的刻度,小数值可以得到更细的表示,同时比例信息也多了一份。实际后端会按张量轴和分组规则组织数据,不能把本例的四个数直接当作某个模型的真实KV分布。

四、运行一个能比较误差的量化器

python 复制代码
def quantize(values, bits):
    limit = 2 ** (bits - 1) - 1
    peak = max(abs(value) for value in values)
    scale = peak / limit if peak else 1.0
    codes = [
        max(-limit, min(limit, round(value / scale)))
        for value in values
    ]
    restored = [code * scale for code in codes]
    error = max(abs(a - b) for a, b in zip(values, restored))
    return codes, restored, error

values = [0.1, 0.2, 0.3, 7.0]
for bits in (4, 8):
    codes, restored, error = quantize(values, bits)
    print(bits, codes, [round(x, 4) for x in restored], round(error, 4))

parts = [values[:3], values[3:]]
errors = [quantize(part, 4)[2] for part in parts]
print("grouped 4-bit max error:", round(max(errors), 4))

运行结果如下。

text 复制代码
4 [0, 0, 0, 7] [0.0, 0.0, 0.0, 7.0] 0.3
8 [2, 4, 5, 127] [0.1102, 0.2205, 0.2756, 7.0] 0.0244
grouped 4-bit max error: 0.0143

Python列表中的整数仍然是Python对象,程序演示的是数值映射,紧凑位存储需要另外实现。这里采用Python的round规则,具体后端的编码、舍入和元数据格式要按其实现核对。

误差较小只说明这组数值恢复得更接近原值。注意力分数、层间传播和生成选择会继续影响输出,应把最终任务质量纳入验收。

五、在生成入口选择缓存策略

模型和输入已经准备好时,可以用下面的参数指定Quanto后端与4位缓存。安装环境还需要该版本要求的后端依赖。

python 复制代码
outputs = model.generate(
    **inputs,
    max_new_tokens=64,
    do_sample=False,
    cache_implementation="quantized",
    cache_config={"backend": "quanto", "nbits": 4},
)

为保持对照条件一致,先用相同模型、输入和解码参数跑常规缓存,再单独运行量化缓存。分别记录输入Token数、输出Token数、GPU峰值、首Token时间和生成阶段延迟。两个运行都完成后,再比较任务正确率、关键字段和停止原因。

一些缓存实现把近期状态保留在高精度区域,积累到一定长度后再量化。这能减少频繁转换,但也增加驻留空间。调整残留长度时,需要同时看长上下文的峰值和短请求的转换成本。

六、按业务目标验收

目标 需要观察的结果 实验设计
容纳更长输入 相同输出上限下能完成的输入长度 逐级增加长度并记录峰值
提高并发 相同延迟目标下可同时服务的请求数 固定输入输出分布
控制质量损失 任务成功率与关键字段差异 使用同一组固定题目和评判规则
控制转换开销 逐Token延迟和总生成时间 分别比较短、中、长上下文

短上下文的缓存本来就小,额外转换可能更显眼。长上下文能省下更多载荷,但也会让量化状态更频繁地参与计算。先选真实业务里需要解决的容量问题,再判断量化策略是否满足延迟和质量要求。

七、🧠 思维导图

#mermaid-svg-d6s3BSue8kbIVAWj{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-d6s3BSue8kbIVAWj .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-d6s3BSue8kbIVAWj .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-d6s3BSue8kbIVAWj .error-icon{fill:#552222;}#mermaid-svg-d6s3BSue8kbIVAWj .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-d6s3BSue8kbIVAWj .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-d6s3BSue8kbIVAWj .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-d6s3BSue8kbIVAWj .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-d6s3BSue8kbIVAWj .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-d6s3BSue8kbIVAWj .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-d6s3BSue8kbIVAWj .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-d6s3BSue8kbIVAWj .marker{fill:#333333;stroke:#333333;}#mermaid-svg-d6s3BSue8kbIVAWj .marker.cross{stroke:#333333;}#mermaid-svg-d6s3BSue8kbIVAWj svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-d6s3BSue8kbIVAWj p{margin:0;}#mermaid-svg-d6s3BSue8kbIVAWj .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-d6s3BSue8kbIVAWj .cluster-label text{fill:#333;}#mermaid-svg-d6s3BSue8kbIVAWj .cluster-label span{color:#333;}#mermaid-svg-d6s3BSue8kbIVAWj .cluster-label span p{background-color:transparent;}#mermaid-svg-d6s3BSue8kbIVAWj .label text,#mermaid-svg-d6s3BSue8kbIVAWj span{fill:#333;color:#333;}#mermaid-svg-d6s3BSue8kbIVAWj .node rect,#mermaid-svg-d6s3BSue8kbIVAWj .node circle,#mermaid-svg-d6s3BSue8kbIVAWj .node ellipse,#mermaid-svg-d6s3BSue8kbIVAWj .node polygon,#mermaid-svg-d6s3BSue8kbIVAWj .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-d6s3BSue8kbIVAWj .rough-node .label text,#mermaid-svg-d6s3BSue8kbIVAWj .node .label text,#mermaid-svg-d6s3BSue8kbIVAWj .image-shape .label,#mermaid-svg-d6s3BSue8kbIVAWj .icon-shape .label{text-anchor:middle;}#mermaid-svg-d6s3BSue8kbIVAWj .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-d6s3BSue8kbIVAWj .rough-node .label,#mermaid-svg-d6s3BSue8kbIVAWj .node .label,#mermaid-svg-d6s3BSue8kbIVAWj .image-shape .label,#mermaid-svg-d6s3BSue8kbIVAWj .icon-shape .label{text-align:center;}#mermaid-svg-d6s3BSue8kbIVAWj .node.clickable{cursor:pointer;}#mermaid-svg-d6s3BSue8kbIVAWj .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-d6s3BSue8kbIVAWj .arrowheadPath{fill:#333333;}#mermaid-svg-d6s3BSue8kbIVAWj .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-d6s3BSue8kbIVAWj .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-d6s3BSue8kbIVAWj .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-d6s3BSue8kbIVAWj .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-d6s3BSue8kbIVAWj .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-d6s3BSue8kbIVAWj .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-d6s3BSue8kbIVAWj .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-d6s3BSue8kbIVAWj .cluster text{fill:#333;}#mermaid-svg-d6s3BSue8kbIVAWj .cluster span{color:#333;}#mermaid-svg-d6s3BSue8kbIVAWj div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-d6s3BSue8kbIVAWj .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-d6s3BSue8kbIVAWj rect.text{fill:none;stroke-width:0;}#mermaid-svg-d6s3BSue8kbIVAWj .icon-shape,#mermaid-svg-d6s3BSue8kbIVAWj .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-d6s3BSue8kbIVAWj .icon-shape p,#mermaid-svg-d6s3BSue8kbIVAWj .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-d6s3BSue8kbIVAWj .icon-shape .label rect,#mermaid-svg-d6s3BSue8kbIVAWj .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-d6s3BSue8kbIVAWj .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-d6s3BSue8kbIVAWj .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-d6s3BSue8kbIVAWj :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} KV缓存量化
容量账本
位宽与紧凑载荷
比例与残留区
数值转换
舍入和反量化
分组与离群值
验收
峰值和逐Token延迟
任务质量

八、总结

总结要点

低位宽能缩小KV数值载荷,完整容量账本还要计入比例信息、高精度区域和工作区。先把节约的字节算清,再去测GPU峰值。

位宽和分组共同决定数值刻度。独立实验能解释离群值怎样压缩普通数值的表示空间,业务评测负责验证这些变化最终能否被接受。

下一篇讨论推理请求的准入控制,把上下文长度、输出预算和可用KV容量放在同一份资源账本里。

👉 如果你觉得这篇文章对你有所帮助,欢迎点赞、收藏、分享!😊

相关推荐
csdn_aspnet16 分钟前
Redis 入门:Windows、Mac安装指南
数据库·windows·redis·缓存·mac
政安晨41 分钟前
【政安晨】嵌入式AI开发实践 —— ESP-Claw 深度拆解:把 AI Agent 塞进 $5 芯片,它是怎么“看见“并“握住“硬件的
人工智能·开源·esp·ai agents·esp-claw·esp-mosaico
卷无止境1 小时前
以 Obsidian 为核心的知识库体系:工具生态、AI 协同与最佳实践方案
人工智能
ShuangNaoPai1 小时前
饱和品类的心智词生成:从“新米”认知到“五新米”的判定路由
人工智能·程序人生·产品·思维·品牌营销
星云_byto1 小时前
CSS布局
人工智能·机器学习·目标跟踪·1024程序员节
天天代码码天天1 小时前
照片和视频之外,微信里的声音也值得好好保存
人工智能
IT_陈寒2 小时前
Java开发实战:从入门到精通
前端·人工智能·后端
lucas_AI2 小时前
560B 只激活 25B:蚂蚁百灵 Ling-3.2-flash 把原生多模态 API 卷到 2 块钱一百万 token
人工智能
lucas_AI2 小时前
OpenAI 融资缩水、Anthropic IPO 被压价:AI 的钱,突然不好融了
人工智能