[控场AI]
科技前沿· 8 分钟阅读· 4,029 字

KV Cache量化实测:8-bit几乎无损,4-bit代价有多大?

KV Cache量化实测:8-bit几乎无损,4-bit代价有多大?

Qwen3.8 27B系统测试显示:8-bit KV cache近乎无损,4-bit需按权重精度谨慎权衡。

该文基于Reddit社区对Qwen3.8 27B的系统性测试,用KL散度和Top-1一致率衡量不同KV cache精度对输出分布的影响,覆盖llama.cpp、exllamav3和vLLM三大引擎及35个权重量化版本。结果显示:8-bit KV cache在llama.cpp和ExLlamaV3上KLD变化在±0.00012以内,近乎免费,内存减半;vLLM的FP8 cache仅有0.0004-0.0006的轻微上升。4-bit cache则带来可测惩罚,且对高精度权重伤害更大——Q8_0上KLD增加约390%,Q3级别仅6-10%,并随上下文增长在16-32k处比前4k高出15-30%。权重量化方面,vLLM检查点仍不敌更小的GGUF/EXL3,激活量化是重要原因,改用Marlin kernel保留bf16激活后NVFP4的KLD减半。作者建议Q5及以上权重优先8-bit KV cache。

KV cache量化一直是本地部署大模型时的争议话题。有人坚持「绝不量化」,也有人认为「4-bit够用」。Reddit社区最近一篇针对Qwen3.8 27B的系统性测试,用KL散度(KLD)量化了不同KV cache精度对模型输出分布的影响,覆盖llama.cpp、exllamav3和vLLM三大推理引擎,测试了35个权重量化版本,每个版本分别搭配16-bit、8-bit和(引擎支持时)4-bit KV cache。结论很明确:8-bit KV cache基本免费,4-bit则需要谨慎权衡。

reddit source: Effects of KV Cache Quantization on Qwen3.8 27B

测试方法:用KL散度衡量输出漂移

作者采用token-by-token的KL散度来衡量量化模型与bf16原始模型的概率分布差异,0表示完全一致。同时统计Top-1一致率——两个模型选中同一个最可能token的频率。为了让不同引擎的结果可比,作者先用无量化模型在llama.cpp和vLLM上跑了一遍对照,两者KLD仅差0.0004,相当于两个正确实现在浮点运算顺序上的差异,因此跨引擎比较KLD数值是成立的。

数据集这次也做了重做,混合了由Qwen3.8 27B全精度生成的agentic工具调用样本和多个领域的文本,单行上下文最长延伸到64k token。每个量化版本都对照未量化的bf16参考模型评分,GGUF和EXL3对照Bartowski的bf16 GGUF,vLLM检查点对照官方bf16 safetensors。

KL散度(Kullback-Leibler Divergence) 衡量的是两个概率分布之间的差异:若用分布Q去近似真实分布P,KLD量化的是平均每个事件上多付出的信息量(以比特或纳特计)。它对「P有概率而Q几乎为零」的情况惩罚极重,因此特别适合检测量化模型是否丢掉了某些本该出现的token。在实际对比LLM输出时,通常对每个位置的完整词表分布计算KLD再取平均,数值越小表示输出分布越接近原模型。需要注意KLD是非对称的,P→Q与Q→P并不相等;本文统一以bf16原模型为参考分布P、量化模型为Q。由于KLD是相对量,不同模型、不同数据集之间的绝对值不可直接横比,这也是作者要先验证跨引擎可比性的原因。

bf16(bfloat16) 是一种16位浮点格式,与常见的fp16位宽相同,但指数位从5位增加到8位、尾数位缩减到7位。指数位与fp32一致意味着bf16拥有和单精度浮点相同的动态范围(约1e-38到3e38),不会像fp16那样在极大或极小值处溢出,代价是有效精度更低(约2-3位十进制)。对神经网络推理而言,动态范围通常比尾数精度更关键,因此bf16成为训练和推理的默认参考精度,也是本文所有KLD对比的基准。

权重量化:vLLM检查点依然不占优

延续Qwen3.6的测试结果,每个vLLM检查点的KLD表现都被更小的GGUF或EXL3量化版本击败。部分原因在于激活量化:NVIDIA和Unsloth的NVFP4检查点将MLP层跑成W4A4(4-bit激活),注意力层为FP8 W8A8;Qwen的FP8则是全程W8A8。

作者用vLLM的Marlin kernel重跑了NVIDIA NVFP4和Qwen FP8,保持量化权重但激活保留bf16:NVFP4的KLD从0.0256降到0.0117,降幅超过一半;FP8从0.0039降到0.0028,降低约30%。即便如此,NVFP4也仅与UD-Q5_K_XL打平,而后者体积小了8.7 GiB。这个结果说明,激活量化对输出分布的影响可能比权重本身更大。

W4A4、W8A8与NVFP4 描述的是权重和激活各自的量化位宽:W指权重(Weight),A指激活(Activation),数字为比特数。W8A8表示权重和激活都用8位整数/浮点表示,是较成熟的部署方案;W4A4则把两者都压到4位,压缩率更高但对数值误差更敏感。NVFP4是NVIDIA提出的4位浮点微缩放格式,采用两级缩放(每个16元素块一个FP8缩放因子,外加全局缩放),相比传统的MXFP4等格式在小块内精度更好,但它默认同时量化权重与激活。Marlin kernel 是vLLM中面向低比特权重的高性能GEMM实现,支持将权重保持4位、激活保留bf16的「仅权重量化」路径,这正是作者重跑实验、把NVFP4的KLD砍半所依赖的手段。可见同一份量化权重,激活是否量化会显著改变输出分布。

KV cache量化:8-bit几乎免费

先看内存收益。以64k上下文为例,16-bit cache每token占64 KiB,总计4.00 GiB;8-bit cache(llama.cpp的q8_0、EXL3 8-bit、vLLM的fp8_e4m3)每token约32-34 KiB,总计约2 GiB,节省约2 GiB;4-bit cache(llama.cpp的q4_0、EXL3 4-bit)每token约18 KiB,总计1.13 GiB,节省2.9 GiB。

llama.cpp和ExLlamaV3的8-bit cache几乎没有代价。所有测试的量化版本上,q8_0和EXL3 8-bit cache带来的KLD变化都在±0.00012以内,部分量化甚至测出略好,说明这完全在数值噪声范围内。vLLM的FP8 cache则有轻微上升,每个检查点增加0.0004到0.0006的KLD,数值依然极小,但几乎在每个prompt上都稳定出现。作者推测这可能是因为开启FP8 cache后,vLLM的注意力后端从FlashAttention切换到了FlashInfer。

4-bit KV cache:代价可测,且与权重精度强相关

llama.cpp的q4_0 cache带来的KLD惩罚大致固定,在测试的GGUF量化上增加+0.0016到+0.0027。但这个绝对增量对越精确的权重伤害越大:在Q3级别量化(KLD约0.025-0.035)上只增加6-10%;在UD-Q4_K_XL上增加约39%;在Q8_0上增加约390%——KLD从0.0007跃升到0.0034,反而比使用16-bit cache的UD-Q5_K_XL更差。

EXL3的4-bit cache惩罚则明显依赖权重精度:2.0-2.5 bpw权重只增加+0.0002到+0.0004;3.0 bpw增加约+0.0021到+0.0022;4.0 bpw增加+0.0026到+0.0028;6.0和8.0 bpw则达到+0.0032到+0.0033。也就是说,如果你本身已经在用低比特权重,4-bit KV cache的边际代价相对可接受;但如果你追求高精度权重,4-bit cache会直接抹掉权重量化的收益。

上下文越长,4-bit惩罚越大

作者用12篇长文档在每个位置打分,发现4-bit cache的惩罚随上下文深度增长而扩大。以Q8_0权重+q4_0 KV为例,前4k token的KLD增加为+0.0035,到16-32k区间升至+0.0041,32-64k文档达到+0.0044。整体来看,16-32k上下文的额外KL比前4k高出约15-30%。相同量化版本搭配16-bit cache时,各上下文长度下KLD不受影响,这清楚表明增量来自4-bit cache本身。作者预期128k以上上下文会更糟。

KV cache 是自回归推理中缓存历史token的Key和Value张量的机制,避免每生成一个新token都重算全部上下文。其显存占用随上下文长度线性增长:每个token的cache大小约为 2 × 层数 × KV头数 × 头维度 × 每元素字节数,因此长上下文下KV cache往往与模型权重相当甚至更大。量化KV cache就是把这些缓存的元素从16位压到8位或4位,直接按比例减少显存。但KV cache与权重不同:它参与注意力的点积计算,量化误差会被softmax放大并逐层传播,而且历史token的误差会持续影响后续所有生成,这也是长上下文下4-bit惩罚随深度累积的机制性原因。llama.cpp的q8_0、q4_0指其通用的块量化格式,每32个元素共享一个缩放因子;vLLM的fp8_e4m3则是8位浮点(4位指数、3位尾数),动态范围更适合激活类数据。

实践建议:按权重精度决定KV策略

综合数据,选择KV cache精度的逻辑应该和权重精度挂钩:

  • 使用Q5及以上精度权重:优先8-bit KV cache。在llama.cpp和ExLlamaV3上几乎零损失,vLLM上代价也极小,能直接省下一半cache内存。4-bit cache不值得,会显著拉低高精度权重的优势。
  • 使用Q3及以下精度权重:8-bit仍是推荐项;4-bit可以作为显存极度紧张时的备选,但需接受长上下文下逐渐累积的分布漂移。
  • 长上下文场景:对4-bit KV cache保持警惕。作者指出,KV cache量化带来的KLD与权重量化KLD在质量权衡上可能不同,社区经验也表明长上下文下KV量化对模型表现的伤害可能大于权重量化。

最后一张汇总图将权重和64k KV cache的总内存与KL divergence对照,推荐线明确排除了4-bit KV。对于大多数本地部署场景,8-bit KV cache是当前性价比最高的选择——省一半内存,几乎不付代价。

#KV cache量化#Qwen3.8 27B#KL散度#llama.cpp#vLLM#8-bit KV cache#4-bit KV cache#本地部署
分享:

相关推荐