Qwen3.8 27B KV Cache量化实测:8位无损4位有损
Effects of KV Cache Quantization on Qwen3.8 27B
本地部署Qwen的同学必看,这篇实测给出了不同引擎下KV Cache量化的具体精度损耗数据,直接指导你如何在显存和精度间做取舍。
KV cache quantization has been a hotly-debated topic for this community for some time, with opinions ranging from "never quantize" to "4 bit is fine". Since the anecdotal evidence is rather inconsistent, I decided to quantify how much KV cache quantization affects the model through KLD, which is a good measure of how the model's output distribution is changed.
KV 缓存量化一直是该社区热烈讨论的话题,观点从“永远不要量化”到“4 bit 就很好”不等。由于轶事证据相当不一致,我决定通过 KLD(KL 散度)来量化 KV 缓存量化对模型的影响程度,KLD 是衡量模型输出分布变化程度的良好指标。
I tested 35 weight quants across llama.cpp, exllamav3, and vLLM, each with 16-bit, 8-bit, and (where supported) 4-bit KV cache. I also reworked my KLD dataset and measurement methodology this time, to include a mix of agentic tool-use (generated by Qwen3.8 27B at full precision) and a variety of texts in different domains. The current dataset now stretches up to 64k token contexts per row.
我在 llama.cpp、exllamav3 和 vLLM 中测试了 35 种权重量化方案,每种都分别使用 16-bit、8-bit 以及(在支持的情况下)4-bit KV 缓存。我还重新改进了本次的 KLD 数据集和测量方法,包含由 Qwen3.8 27B 在全精度下生成的智能体工具使用数据,以及不同领域的多种文本。当前数据集每行可覆盖高达 64k token 的上下文。
TLDR;
TLDR(太长不看):
- 8-bit KV caches work well. In llama.cpp and ExLlamaV3 the cache size is halved, and there’s essentially no difference in KLD. There’s a slight difference in vLLM, but it’s still a great tradeoff for people lacking VRAM.
- A 4-bit cache has a measurable impact. It’s a big hit for ~Q8 weights, but it could potentially be worth it if you’re using Q3 or below. Still, not recommended.
- Only the 4-bit cache impact grows with context. In the tested long documents, the added KL is about 15-30% higher at 16-32k tokens than in the first 4k.
- 8-bit KV 缓存效果良好。在 llama.cpp 和 ExLlamaV3 中,缓存大小减半,而 KLD 几乎没有差异。vLLM 中存在轻微差异,但对于缺乏 VRAM 的用户来说,这仍然是一个极佳的权衡。
- 4-bit 缓存会产生可测量的影响。对于 ~Q8 权重而言,这是一个重大损失;但如果你使用的是 Q3 或更低精度的权重,它可能值得尝试。尽管如此,仍不推荐。
- 只有 4-bit 缓存的影响随上下文长度增长。在测试的长文档中,16-32k token 处的额外 KL 散度比前 4k token 高出约 15-30%。
The blog post has interactive charts and tables with all of the data and results if you're interested.
如果你对数据和结果感兴趣,博客文章中提供了包含所有数据和结果的交互式图表和表格。
How to read the numbers
如何解读这些数字
Each quant is compared token-by-token with an unquantized bf16 copy of the model. KL divergence measures how far the quant’s next-token probabilities drift from the original (0 means no change). Top-1 agreement is how often both models pick the same most likely token.
每种量化方案都与模型未量化的 bf16 副本进行逐 token 比较。KL 散度衡量的是量化模型的下一个 token 概率偏离原始模型的程度(0 表示无变化)。Top-1 一致性是指两个模型选择相同最可能 token 的频率。
For a reference point, I ran the unquantized model in both llama.cpp and vLLM and compared the two. They differ by a KL of 0.0004, which essentially amounts to two (correct) implementations doing floating-point math in a different order. Thus, you can compare the KLD numbers here for quants running in different engines without issue.
作为参考基准,我在 llama.cpp 和 vLLM 中均运行了未量化的模型并进行了比较。两者的差异为 0.0004 的 KL 散度,这本质上是由于两种(正确的)实现以不同的顺序执行浮点运算所致。因此,你可以放心地比较在不同引擎中运行的量化方案的 KLD 数值。
Note: exllamav3 quants were measured with the bf16 llama.cpp reference logits.
注意:exllamav3 的量化方案是使用 bf16 llama.cpp 参考 logits 进行测量的。
Weight quantization
权重量化
KL divergence vs. loaded weight size, 16-bit KV cache:
KL 散度与加载权重大小的关系,16-bit KV 缓存:
The blog post has an interactive chart and the full KLD numbers in a table, check that out if you're interested.
博客文章中提供了交互式图表和包含完整 KLD 数值的表格,感兴趣的话可以查看。
The vLLM checkpoints still do worse
vLLM 的检查点表现仍然较差
As in the Qwen3.6 benchmarks, every vLLM checkpoint is beaten by a smaller GGUF or EXL3 quant. Some of that is due activation quantization. NVIDIA’s and Unsloth’s NVFP4 checkpoints run the MLP layers as W4A4 (4-bit activations) and attention as FP8 W8A8, and Qwen’s FP8 is W8A8 throughout. I reran NVIDIA’s NVFP4 and Qwen’s FP8 through vLLM’s Marlin kernels, which use the same quantized weights but keep the activations in bf16:
正如 Qwen3.6 基准测试所示,每个 vLLM 检查点都被更小的 GGUF 或 EXL3 量化版本超越。部分原因在于激活值量化。NVIDIA 和 Unsloth 的 NVFP4 检查点将 MLP 层作为 W4A4(4-bit 激活值),注意力机制作为 FP8 W8A8,而 Qwen 的 FP8 全程采用 W8A8。我通过 vLLM 的 Marlin 内核重新运行了 NVIDIA 的 NVFP4 和 Qwen 的 FP8,这些内核使用相同的量化权重但保持激活值为 bf16:
- NVFP4: KL drops from 0.0256 to 0.0117, more than halving it.
- FP8: KL drops from 0.0039 to 0.0028, about 30% less. Even then it only ties UD-Q5_K_XL, which is 8.7 GiB smaller.
- NVFP4:KL 从 0.0256 降至 0.0117,降幅超过一半。
- FP8:KL 从 0.0039 降至 0.0028,减少约 30%。即便如此,它仅与 UD-Q5_K_XL 持平,而后者体积小 8.7 GiB。
KV cache quantization
KV 缓存量化
| KV cache | Per token | At 64k context | Saved vs. 16-bit |
|---|---|---|---|
| f16 / bf16 | 64 KiB | 4.00 GiB | - |
| 8-bit: llama.cpp q8_0, EXL3 8-bit | 34 KiB | 2.13 GiB | 1.9 GiB |
| 8-bit: vLLM fp8_e4m3 | 32 KiB | 2.00 GiB | 2.0 GiB |
| 4-bit: llama.cpp q4_0, EXL3 4-bit | 18 KiB | 1.13 GiB | 2.9 GiB |
| KV 缓存 | 每 token | 在 64k 上下文下 | 相比 16-bit 节省 |
|---|---|---|---|
| f16 / bf16 | 64 KiB | 4.00 GiB | - |
| 8-bit: llama.cpp q8_0, EXL3 8-bit | 34 KiB | 2.13 GiB | 1.9 GiB |
| 8-bit: vLLM fp8_e4m3 | 32 KiB | 2.00 GiB | 2.0 GiB |
| 4-bit: llama.cpp q4_0, EXL3 4-bit | 18 KiB | 1.13 GiB | 2.9 GiB |
Each dot below is one weight quant with an 8-bit or 4-bit KV cache. Its height shows the KL increase compared with the same weights on a 16-bit cache. Zero means no change; higher points show a larger increase. I computed the differences per prompt on identical tokens.
下方的每个点代表一个具有 8-bit 或 4-bit KV 缓存的权重量化。其高度显示与相同权重在 16-bit 缓存上相比 KL 的增加量。零表示无变化;较高的点表示增加幅度更大。我在相同的 token 上针对每个提示计算了差异。
KV cache penalty vs loaded weight size:
KV 缓存惩罚 vs 加载权重大小:
Open markers show 8-bit KV; filled markers show 4-bit KV. Colors identify the engines. The dotted line marks the KL difference between the two bf16 reference engines. vLLM has no 4-bit KV cache option.
空心标记显示 8-bit KV;实心标记显示 4-bit KV。颜色标识引擎。虚线标记了两个 bf16 参考引擎之间的 KL 差异。vLLM 没有 4-bit KV 缓存选项。
8-bit is essentially free in llama.cpp and ExLlamaV3. For every quant, q8_0 and ExLlamaV3’s 8-bit cache move KL by less than 0.00012 in either direction. Some quants even measure slightly better with it, which indicates it’s within the noise of the numerics.
在 llama.cpp 和 ExLlamaV3 中,8-bit 几乎是免费的。对于每种量化,q8_0 和 ExLlamaV3 的 8-bit 缓存使 KL 的变化小于 0.00012。某些量化甚至测量出略好的结果,这表明它在数值噪声范围内。
vLLM’s FP8 cache shows a slight KLD increase. It adds 0.0004 to 0.0006 on every checkpoint, which is still extremely small, but it shows up on nearly every prompt. It may be due to turning on FP8 cache switching vLLM’s attention backend from FlashAttention to FlashInfer.
vLLM 的 FP8 缓存显示出轻微的 KLD 增加。它对每个检查点增加了 0.0004 到 0.0006,这仍然非常小,但在几乎每个提示中都会出现。这可能是由于开启 FP8 缓存切换导致 vLLM 的注意力后端从 FlashAttention 变为 FlashInfer。
llama.cpp’s 4-bit cache adds a roughly fixed penalty. Across the GGUF quants tested, q4_0 adds +0.0016 to +0.0027 KL. This increase has a larger relative effect on more precise weights:
llama.cpp 的 4-bit 缓存增加了一个大致固定的惩罚。在测试的 GGUF 量化中,q4_0 增加了 +0.0016 到 +0.0027 的 KL。这种增加对更精确的权重有更大的相对影响:
- On a Q3-class quant (KL around 0.025-0.035) it adds 6-10%.
- On UD-Q4_K_XL it adds about 39%.
- On Q8_0 it adds about 390%. KL goes from 0.0007 to 0.0034, which is worse than UD-Q5_K_XL with a 16-bit cache.
- 在 Q3 类量化(KL 约为 0.025-0.035)上,它增加了 6-10%。
- 在 UD-Q4_K_XL 上,它增加了约 39%。
- 在 Q8_0 上,它增加了约 390%。KL 从 0.0007 变为 0.0034,这比带有 16-bit 缓存的 UD-Q5_K_XL 更差。
EXL3’s 4-bit cache penalty seems to depend on weight precision. It adds only +0.0002 to +0.0004 KL with 2.0-2.5 bpw weights, about +0.0021 to +0.0022 with 3.0 bpw weights, and +0.0026 to +0.0028 with 4.0 bpw weights. At 6.0 and 8.0 bpw, the penalty reaches about +0.0032 to +0.0033. The increase is therefore not constant across the EXL3 quants.
EXL3 的 4-bit 缓存惩罚似乎取决于权重精度。在 2.0-2.5 bpw 权重下,它仅增加 +0.0002 到 +0.0004 的 KL 值;在 3.0 bpw 权重下,约为 +0.0021 到 +0.0022;在 4.0 bpw 权重下,为 +0.0026 到 +0.0028。在 6.0 和 8.0 bpw 时,惩罚达到约 +0.0032 到 +0.0033。因此,该惩罚在 EXL3 量化中并非恒定不变。
4-bit cache penalty grows with context
4-bit 缓存惩罚随上下文长度增长
The 12 long documents in the set are scored at every position, so I can check whether the 4-bit penalty depends on how deep into the context a token is. It does in fact grow slightly.
数据集中的 12 篇长文档在每个位置都进行了评分,因此我可以检查 4-bit 惩罚是否依赖于 token 在上下文中的深度。事实上,它确实略有增长。
| Position | Q8_0 Weights + q4_0 KV | UD-Q5_K_XL Weights + q4_0 KV | EXL3 8.0 BPW Weights + 4-bit KV |
|---|---|---|---|
| First 4k tokens | +0.0035 | +0.0030 | +0.0041 |
| 4k–8k | +0.0037 | +0.0033 | +0.0044 |
| 8k–16k | +0.0040 | +0.0036 | +0.0047 |
| 16k–32k | +0.0041 | +0.0038 | +0.0050 |
| 32k–64k (one document) | +0.0044 | +0.0038 | +0.0053 |
| 位置 | Q8_0 权重 + q4_0 KV | UD-Q5_K_XL 权重 + q4_0 KV | EXL3 8.0 BPW 权重 + 4-bit KV |
|---|---|---|---|
| 前 4k tokens | +0.0035 | +0.0030 | +0.0041 |
| 4k–8k | +0.0037 | +0.0033 | +0.0044 |
| 8k–16k | +0.0040 | +0.0036 | +0.0047 |
| 16k–32k | +0.0041 | +0.0038 | +0.0050 |
| 32k–64k(一篇文档) | +0.0044 | +0.0038 | +0.0053 |
There’s about 15-30% more damage at 16-32k context than in the first 4k tokens. The same quants with a 16-bit cache are unaffected across these context lengths, so it’s a pretty clear indication of the 4 bit cache damage. I would expect 128k+ context lengths to be even worse.
在 16k-32k 上下文中,损害比前 4k tokens 多出约 15-30%。使用 16-bit 缓存的相同量化在这些上下文长度下不受影响,因此这清楚地表明了 4-bit 缓存造成的损害。我预计 128k+ 的上下文长度情况会更糟。
Model quantization KLD vs KV cache KLD:
模型量化的 KLD 与 KV 缓存的 KLD:
KLD due to KV cache quantization likely has different quality tradeoffs compared to KLD from weight quantization. Anecdotal evidence suggests that KV cache quantization can be more harmful to model performance at long context lengths compared to weight quantization, so be wary of using 4-bit KV cache.
由于 KV 缓存量化导致的 KLD 可能与权重量化导致的 KLD 有不同的质量权衡。轶事证据表明,与权重量化相比,KV 缓存量化在长上下文长度下对模型性能的损害更大,因此请谨慎使用 4-bit KV 缓存。
Final chart with weights + 64k KV cache versus KL divergence:
包含权重与 64k KV 缓存的最终图表及 KL 散度:
The line highlights the recommended quants, excluding 4-bit KV. Diamonds show 8-bit KV; faded circles and triangles show 16-bit and 4-bit KV. Memory includes weights and the KV cache at 64k context.
线条高亮了推荐的量化方案,排除了 4-bit KV。菱形表示 8-bit KV;淡色圆形和三角形分别表示 16-bit 和 4-bit KV。内存占用包括权重以及在 64k 上下文下的 KV 缓存。
Methodology
方法论
Each quant was scored against an unquantized bf16 reference:
每个量化版本均与未量化的 bf16 参考模型进行评分对比:
- GGUF and EXL3 quants scored against Bartowski’s bf16 GGUF in llama.cpp.
- vLLM checkpoints scored against the official bf16 safetensors in vLLM.
- GGUF 和 EXL3 量化版本在 llama.cpp 中与 Bartowski 的 bf16 GGUF 进行评分对比。
- vLLM 检查点在与 vLLM 中官方 bf16 safetensors 的对比中进行评分。
KL is computed the same way as my previous benchmark. The top 200 log probabilities are taken from both models at each position and a lower bound on the full-vocabulary D_KL(P_reference ‖ P_quant) is computed. On average, the reference put 0.0036 of its probability outside its top 200 tokens. The KV deltas are paired, meaning they’re computed from per-prompt differences on identical tokens.
KL 的计算方式与我之前的基准测试相同。在每个位置,从两个模型中获取前 200 个对数概率,并计算完整词汇表 D_KL(P_reference ‖ P_quant) 的下界。平均而言,参考模型将其 0.0036 的概率分布在其前 200 个 token 之外。KV 差值是配对的,意味着它们是根据相同 token 上的逐提示差异计算的。
Checkpoints ran with their declared settings, including any activation quantization (except the two weight-only, no activaton quantization reruns of Unsloth’s NVFP4 and the official FP8 quant).
检查点按其声明的设置运行,包括任何激活量化(Unsloth 的 NVFP4 和官方 FP8 量化的两次仅权重、无激活量化的重跑除外)。
更进一步:量化金融体系
看懂新闻只是起点——沿量化金融路径,把它变成能交付的工程能力