量化 KV 缓存:节省 VRAM(长 contexte)
您的显存足以加载模型,但一旦将上下文扩展到 16k 或 32k 个 token,就会超出显存容量。罪魁祸首是 KV 缓存:一块不显眼的内存开销,随上下文长度线性增长,在提示词很长时,占用空间可能与模型本身一样大。KV 缓存量化将其压缩为 Q8 或 Q4,让同一张显卡能承载的上下文长度翻倍。下面介绍如何在 Ollama 和 llama.cpp 中启用这一功能、收益的具体数值,以及对质量的实际影响。
#为什么 KV 缓存会占用你的 VRAM
大语言模型生成文本时,不会在每生成一个新 token 时重新计算整个提示词的注意力,而是将此前见过的每个 token 的键(K)和值(V)向量保存在内存中。这就是 KV 缓存,也是文本生成能够保持快速的原因。问题在于:它占用的内存会随着上下文长度线性增长。上下文长度翻倍,KV 缓存也会翻倍。
对于只有几百个 token 的短提示词,这部分占用可以忽略不计。但一旦用大型文档做 RAG、总结转录文本,或使用具有长期记忆的智能体,上下文就会急剧膨胀,KV 缓存也随之增大。对于上下文长度为 32k 的 70B 模型,仅 KV 缓存就可能超过 10 GB,此外还有模型本身约 40 GB 的占用。面对长提示词时,导致内存不足的往往是 KV 缓存,而不是模型本身。
#您的 KV 缓存占用多少内存
只需 1 小时,即可在您的电脑上拥有专属的免费 ChatGPT — LM Studio、Ollama、Open WebUI、您的文档,无需云端。
- 在线空间,终身可用
- PDF + 文件
- 30 天内退款
KV 缓存的大小取决于四个因素:模型的层数、注意力维度、上下文长度以及存储精度。在 FP16(默认情况)下,近似公式为:2(K 和 V)× 层数 × dim_kv × 上下文长度 × 2 字节。在实际应用中,记住以下 FP16 情况下上下文长度为 32k token 的数量级:
- 7-9B(例如 Qwen 3.5 9B,Granite 4.2 8B)
- 在 32k 上下文长度下,KV 缓存约占 2 至 4 GB,具体取决于架构(GQA 很有帮助)。
- 14B
- 约4至6 GB,对应32k token。
- 32B
- 上下文为 32k tokens 时,约占用 8 至 10 GB。
- 70B
- 上下文为 32k token 时约需 10 至 16 GB——这往往是限制因素。
#KV缓存量化带来的变化
思路与模型权重类似:而不是以 16 位(FP16)存储缓存中的每个值,而是以 8 位(Q8_0)或 4 位(Q4_0)存储。这会将缓存内存机械地除以 2(Q8)或 4(Q4)。由于 KV 缓存会在长上下文场景中占据大量 VRAM,因此节省效果显著:在 VRAM 不变的情况下,使用 Q8 可以将可支持的上下文长度大致翻倍。
- FP16
- 基准精度,没有损失,但资源消耗最大。默认选项。
- Q8_0
- 内存减少一半,大多数模型的质量损失几乎无法察觉。最佳折衷方案。
- Q4_0
- 内存占用减少四分之三,但可测量的质量损失因模型而异。仅在VRAM确实是瓶颈时使用。
#在 Ollama 中启用KV量化
Ollama 通过两个守护进程环境变量暴露 KV 缓存的量化功能。需要先启用 Flash Attention,然后选择缓存类型。这些变量配置在 Ollama 服务上,而不是在 ollama run 时设置。
- 01启用 Flash Attention在守护进程环境中设置 OLLAMA_FLASH_ATTENTION=1。这是所有非 FP16 缓存的必要前提。
- 02选择缓存类型通过设置OLLAMA_KV_CACHE_TYPE指定所需值:f16(默认)、q8_0(推荐)或q4_0(激进)。
- 03重启守护进程环境变量仅在服务启动时读取。请重启 Ollama 以使设置生效。
- 04验证改善效果加载一个具有大上下文的模型,并使用nvidia-smi或ollama ps监控VRAM。您应能将num_ctx提升到之前更高的水平。
#在 llama.cpp 中启用
通过 llama.cpp 命令行,KV 缓存的量化通过两个独立的标志分别控制键(K)和值(V),并配合 Flash Attention 标志。K 和 V 可独立量化,但实际使用中通常保持相同级别。
- -fa
- 启用 Flash Attention。未设置此标志时,若 -ctk/-ctv 指定的精度低于 f16,就会失败。
- -ctk q8_0
- 将键缓存量化为 8 位。可选值:f16、q8_0、q4_0、q4_1、q5_0、q5_1。
- -ctv q8_0
- 量化值缓存。可选值与 -ctk 相同。
- -c 32768
- 您希望使用的上下文长度。量化让您能够增大这一长度,而不超出显存容量。
#上下文长度能增加多少:实际数据
实际收益取决于 KV 缓存在您的显存预算中占多大比例。如果模型能轻松装入显存,量化缓存只会多腾出一点空间。如果模型已经占满显存,量化缓存则可能决定上下文长度能达到 8k 还是 24k。以下是在显存容量不变的情况下观察到的大致量级:
- FP16 → Q8_0
- 缓存减半。实际上,当缓存主导预算时,可支持的上下文大约翻倍。
- FP16 → Q4_0
- 缓存分为4部分。上下文长度可达到~3-4倍,但会带来可测量的质量损失。
- RTX 4080 16GB 上运行 14B 模型示例
- 使用 FP16 时,上下文约为 16k;使用 Q8_0 时,可达到约 32k 或更多,而模型及其余部分仍可容纳在同样的 16 GB 内存中。
- 示例:在配备 24 GB 显存的 RTX 4090 上运行 32B 模型
- 将缓存改为 Q8_0 量化,往往就能处理用于 RAG 的长文档,而无需将部分计算卸载到 CPU。
#对质量的影响因模型而异
这才是真正的问题。量化缓存会引入注意力机制中的噪声,且不同模型对此的反应各不相同。社区测试中得出的经验法则如下:
- 缓存采用 Q8_0 量化
- 在绝大多数模型上,差异几乎无法察觉。困惑度和主观感受到的质量都与 FP16 几乎相同。这个设置应默认启用,几乎无需犹豫。
- Q4_0 缓存
- 质量损失明显,且程度不一。有些模型能很好地承受这种影响,另一些则会在超长上下文中开始胡言乱语、丢失思路或产生更多幻觉。需要在您自己的使用场景中测试。
- GQA模型
- 通常更能承受缓存量化的影响,因为其缓存本身已经紧凑且结构良好。
- 对精度敏感的任务(代码、计算、严格的信息提取)
- 更容易受到 Q4 量化导致的性能下降影响。凡是需要事实准确性的任务,都应保持使用 Q8。
#故障排除
- “flash attention required”或缓存被忽略
- 您忘记设置 -fa(llama.cpp)或 OLLAMA_FLASH_ATTENTION=1(Ollama)。量化缓存会在没有提示的情况下回退为 FP16,或触发错误。
- 未观察到VRAM使用量的减少
- 您的上下文太短,缓存占用的显存还不明显。只有提示较长时,才能看到节省显存的效果。请增大 num_ctx / -c 来观察这一效果。
- 提示词较长时,质量会下降
- 您很可能使用了 Q4 量化,而该模型在这种量化下表现不佳。请将 K 改回 q8_0(甚至全部改回 q8_0),然后重新测试。
- Ollama 变量未生效
- 这些配置仅在服务启动时读取一次。设置完成后,请重启服务,并确认 ollama 进程能够正确读取这些配置。
- 即使量化后仍出现 OOM
- 超出内存容量的是模型本身,而不是缓存。也对权重进行量化(Q4_K_M),或改用规模小一档的模型。
#深入了解
KV 缓存量化是在本地支持大上下文的多种手段之一。以下指南可补充这一主题的介绍:
- 在本地LLM中启用并测试Flash Attention 2的性能提升
- 这是 KV 量化的前提,本身也能节省内存并提升速度。如果您尚未启用 Flash Attention,请先阅读这篇指南。
- 选择量化方案(Q4、Q5、Q8、FP16)
- 用于量化模型权重——权重是显存占用的另一大来源,权重量化与缓存量化相辅相成。
- 安装 Ollama:Windows、macOS 和 Linux
- 如果您的技术栈尚未搭建,可从这里入手;其中也列出了 GPU 要求,帮助您合理确定硬件配置。
有反馈、发现了错误,或想补充说明?请告诉我们,让这份指南对每个人都更有帮助。