lama.cpp 已处理内容(KV/Prompt)缓存完整配置指南

llama.cpp 里“已处理文本缓存”的本质是 KV Cache:模型把系统提示、长对话前缀计算后的 Key/Value 张量存下来,重复请求无需重新全量预填充(prefill),速度可提升数倍。下面按使用场景把四种机制拆开讲,并给出可直接套用的生产配置。

🔧 本文所有参数都支持两种写法:命令行长选项(如 --cache-ram)或环境变量(LLAMA_ARG_CACHE_RAM)。环境变量规则为「长选项名全大写、连字符变下划线、加 LLAMA_ARG_ 前缀」;布尔取反用 LLAMA_ARG_NO_ 前缀。可配合 Windows 环境变量编辑器一键配置。

一、内存前缀自动复用(server 默认开启,最常用)

这是同模型多请求共享相同前缀(固定 System 提示、通用模板)时的首选方案。llama-server 默认开启 prompt caching(--cache-prompt),配合 unified KV(slot 数为 auto 时默认启用),相同前缀在并发请求 / 多会话间直接复用 KV 张量,跳过重复 prefill;进程重启缓存会丢失。

参数 别名 默认值 环境变量 作用
--cache-prompt --no-cache-prompt 开启 LLAMA_ARG_CACHE_PROMPT 前缀复用主开关(server-only)
--cache-ram N -cram 8192 MiB
(-1=无限制,0=禁用)
LLAMA_ARG_CACHE_RAM 内存缓存容量上限;decision model 默认禁用,需显式设 N
--kv-unified --no-kv-unified slot 数为 auto 时开启 LLAMA_ARG_KV_UNIFIED 所有序列共享同一份 KV 缓冲
--kv-unified-per-slot N — 0(不限制) LLAMA_ARG_KV_UNIFIED_PER_SLOT 每 slot 上下文上限;不设 -c 时共享池 = n_parallel×N
--cache-idle-slots --no-cache-idle-slots 开启 LLAMA_ARG_CACHE_IDLE_SLOTS 新任务开始时把空闲 slot 的 KV 写入 prompt cache 文件;使用 unified KV 时清空(需 --cache-ram)
--cache-reuse N — 0(关闭) LLAMA_ARG_CACHE_REUSE 通过 KV shifting 复用的最小 chunk 尺寸,需 prompt caching 开启;部分模式(多模态/特定组合)下会被忽略
⚠️ 概念澄清:前缀复用的主开关是 --cache-prompt(server 默认已开),不是 --cache-reuse。--cache-reuse N 默认值为 0(关闭),它只是“KV shifting 复用的最小 chunk 尺寸”,设为 512/1024 可启用但非必需,且在某些模式下会被忽略。

环境变量启动(PowerShell)

$env:LLAMA_ARG_CACHE_RAM=16384
$env:LLAMA_ARG_CACHE_REUSE=512
llama-server -m qwen3-8b.gguf -c 8192 -ngl 35

等价命令行(cmd)

set LLAMA_ARG_CACHE_RAM=16384
set LLAMA_ARG_CACHE_REUSE=512
llama-server -m qwen3-8b.gguf -c 8192 -ngl 35 --cache-ram 16384 --cache-reuse 512

二、持久化 Prompt Cache 文件(仅 CLI)

把固定系统提示词、超长前置文档一次性计算后,保存为 .bin 缓存文件,下次启动直接加载,跳过 prefill。注意:此功能仅 llama-cli / perplexity / completion 示例可用,server 无此参数、也无对应环境变量。

参数 作用
--prompt-cache FNAME 把 prompt 状态缓存到文件,下次启动跳过 prefill(默认 none)
--prompt-cache-all 把用户输入与生成也写入缓存
--prompt-cache-ro 只读使用缓存、不更新
# 第一次:带完整 system prompt 生成缓存
llama-cli -m model.gguf -c 8192 --prompt-cache sys_cache.bin -f system_prompt.txt
# 之后:直接加载,跳过 prefill
llama-cli -m model.gguf -c 8192 --prompt-cache sys_cache.bin
server 的“前缀复用”用的是 --cache-prompt(内存级),与这里的磁盘文件 --prompt-cache 不是一回事,别混用。

三、Server 多 slot 持久化(断点续聊)

llama-server 每个对话是独立的 slot。手动保存 / 加载单条对话的完整 KV 缓存,重启服务后仍可恢复聊天上下文。

参数 默认值 环境变量 作用
--slot-save-path PATH disabled LLAMA_ARG_SLOT_SAVE_PATH 开启 slot save/restore API;目录必须预先存在,否则启动直接报错
--slots / --no-slots 开启 LLAMA_ARG_ENDPOINT_SLOTS 暴露 GET /slots 监控端点

HTTP API(端点默认已开启)

# 查看各 slot 状态(验证命中用)
GET  http://127.0.0.1:8080/slots

# 保存某个 slot 的 KV 缓存到 slot-save-path 目录
POST http://127.0.0.1:8080/slots/1?action=save
Content-Type: application/json
{ "filename": "chat1.bin" }

# 恢复(同一端点,action=restore,不是 /slots/restore)
POST http://127.0.0.1:8080/slots/1?action=restore
Content-Type: application/json
{ "filename": "chat1.bin" }

# 清除该 slot 的 prompt cache
POST http://127.0.0.1:8080/slots/1?action=erase

返回示例(save):{ "id_slot":0, "filename":"x.bin", "n_saved":1745, "n_written":14309796, "timings":{"save_ms":49.86} }

❌ 未加 --slot-save-path 就调用会返回:"This server does not support slots action. Start it with --slot-save-path"。

启动(PowerShell)

# 目录要先建好:New-Item -ItemType Directory -Path D:\llama_cache\slots
$env:LLAMA_ARG_SLOT_SAVE_PATH="D:\llama_cache\slots"
llama-server -m model.gguf -c 16384 -ngl 40 --port 8080

四、长上下文 / 低资源:KV 量化 + KV 卸载

❌ 不存在的“SSD 磁盘 KV Offload”:上游 llama.cpp 没有 LLAMA_SSD=1 编译开关,src/llama.cpp 无磁盘溢出逻辑,也无 LLAMA_ARG_SSD_CACHE* 参数。任何中文博客讲的“编译开启 SSD 缓存”都是以讹传讹,加了只会被忽略或报错。

真正可用、且上游确实存在的长上下文手段:

  1. KV 量化(所有模式通用)—— 见第五节。
  2. KV 设备级卸载:--kv-offload / --no-kv-offload(-kvo,默认开启)→ LLAMA_ARG_KV_OFFLOAD。把 KV cache 放到另一后端(第二块 GPU / CPU),不是磁盘。多卡 / 异构机器才有意义。
  3. Context checkpoints:--ctx-checkpoints N(默认 32)、--checkpoint-min-step(默认 8192)→ LLAMA_ARG_CTX_CHECKPOINTS / LLAMA_ARG_CHECKPOINT_MIN_SPACING_NT。在 slot 内保存多个上下文检查点,配合 slot save 一起持久化,适合长文档断点续读。
  4. Context shift:--context-shift(无限生成默认开启)。上下文超长时自动移位避免 OOM。
低内存 CPU 机器的正确做法:开大 -c,用 q4_0 量化 KV,靠 RAM + context-shift;不要使用不存在的 SSD 参数。

五、多 GPU 实战:KV 卸载与选卡

当你有多块显卡(例如一块 32G、一块 16G)时,自然会想让某块卡专职做 KV 缓存。这里必须先说清 --kv-offload 的真实行为,否则很容易配错。

❌ 关键事实:--kv-offload / --no-kv-offload(-kvo)只是 KV 卸载的全局开关(默认开启),它不指定把 KV 放到哪块卡,更做不到“某块卡只放 KV”。源码里第 N 层权重的 KV 固定落在承载该层权重的同一块设备上,因此 KV 缓存永远与各层权重同卡。选卡由 --split-mode / --tensor-split / --main-gpu / --devices 决定。

所以 llama.cpp 没有“A 卡纯推理、B 卡纯 KV”这种拓扑。要让第二块卡的显存用来放 KV,唯一办法是让它也承载一部分层的权重——那部分 KV 会自然跟过来。

相关选卡参数

参数 环境变量 作用
--kv-offload / --no-kv-offload LLAMA_ARG_KV_OFFLOAD KV 卸载开关(默认开启);不负责选卡
--split-mode {none,layer,row,tensor} — 多卡切分方式;layer(默认)按层切并同时切 KV;none 只用单卡
--tensor-split N0,N1,... — 各卡分配比例,如 2,1
--main-gpu INDEX — split-mode=none 时的唯一卡;row 模式下的中间结果与 KV 卡
--devices LIST LLAMA_ARG_DEVICE 指定用于 offload 的设备列表(none = 不 offload)
先确认设备顺序:用 llama-server --list-devices 或 nvidia-smi 看哪块是 index 0。下面假设 32G 卡 = 设备 0,16G 卡 = 设备 1。若想强制 32G 卡为 0,启动前 set CUDA_VISIBLE_DEVICES=<32G卡的id>,<16G卡的id>。

方案 A:32G 卡全包,16G 卡空闲

若模型 + KV 全塞进 32G 就够,根本不需要第二块卡:

# 单卡模式:全部放 main-gpu 0(32G 卡),16G 卡不参与
llama-server -m model.gguf -ngl 99 -c 8192 --split-mode none --main-gpu 0

此时“第一块负责推理”成立,但第二块卡没用上。

方案 B:两块卡都用(推荐,第二块卡显存被 KV + 部分层用上)

把模型按显存比例分层到两块卡,每块卡既放自己那部分权重也放对应 KV,这是 32G+16G 的标准多卡用法:

# 32G 卡拿 2 份、16G 卡拿 1 份权重与 KV(按比例分层,pipelined)
llama-server -m model.gguf -ngl 99 -c 32768 --split-mode layer --tensor-split 2,1
  • --tensor-split 2,1 表示设备 0 占 2/3、设备 1 占 1/3;比例接近显存比即可,想更激进可 3,2 让 16G 卡多带点。
  • 16G 卡确实“持有 KV”,只是它同时也算自己那 1/3 层的推理——这是当前架构下最贴近目标的形态。

六、KV 缓存压缩(降低显存 / 内存占用)

修改 KV 存储精度可大幅减少缓存体积,与上面所有缓存机制叠加使用。

参数 环境变量 允许值 效果
--cache-type-k TYPE LLAMA_ARG_CACHE_TYPE_K f32, f16, bf16, q8_0, q4_0, q4_1, iq4_nl, q5_0(及更多) K 向量量化
--cache-type-v TYPE LLAMA_ARG_CACHE_TYPE_V V 向量量化
  • 默认均为 f16(2 字节/值)。
  • 推荐 q8_0:几乎无损、缓存体积减半;或 q4_0:体积降为 1/4,质量轻微损失。

七、推荐生产配置

桌面 GPU(8G 显存,多请求共享 System 提示)

# 线程数(注意:变量是 LLAMA_ARG_THREADS,不是 LLAMA_NUM_THREADS)
LLAMA_ARG_THREADS=12
LLAMA_ARG_CTX_SIZE=8192
LLAMA_ARG_N_GPU_LAYERS=35
# 缓存核心(server 默认已开 --cache-prompt,无需再设)
LLAMA_ARG_CACHE_RAM=16384
LLAMA_ARG_CACHE_REUSE=512
# kv-unified 在 slot 为 auto 时默认开,下面一行可省略
LLAMA_ARG_KV_UNIFIED=1
LLAMA_ARG_CACHE_IDLE_SLOTS=1
# KV 量化省显存
LLAMA_ARG_CACHE_TYPE_K=q8_0
LLAMA_ARG_CACHE_TYPE_V=q8_0
# 对话持久化(目录须先建好)
LLAMA_ARG_SLOT_SAVE_PATH=D:\AI\llama_kv_slots

低内存 CPU 机器(无 SSD 参数,改为 KV 量化 + context-shift)

LLAMA_ARG_CTX_SIZE=32768
# 不要加 LLAMA_ARG_SSD_CACHE / LLAMA_ARG_SSD_CACHE_PATH(上游不存在)
LLAMA_ARG_CACHE_TYPE_K=q4_0
LLAMA_ARG_CACHE_TYPE_V=q4_0
LLAMA_ARG_CACHE_RAM=4096
# 若有多设备可加:LLAMA_ARG_KV_OFFLOAD=1

八、常见问题

  1. 缓存不生效,每次都完整 prefill
    • server 确认 --cache-prompt 已开(默认开);decision model 需显式 --cache-ram N。
    • 前缀复用靠 unified KV + prompt caching;--cache-reuse 只影响 KV-shifting 复用、默认 0,不会让前缀复用失效。
    • 前缀 token 必须 ≥ 某长度才会复用——这由 unified KV 的前缀匹配决定,不是 cache-reuse 阈值。
  2. slot 保存 API 找不到
    • 必须配置 --slot-save-path 且目录已存在,否则返回不支持的提示。
  3. 配置 SSD 缓存报错
    • 该功能根本不存在,任何 LLAMA_SSD* / LLAMA_ARG_SSD_CACHE* 都会被忽略或报错,直接删掉即可。
  4. 内存占用持续上涨
    • 调低 LLAMA_ARG_CACHE_RAM,或保留默认的 --cache-idle-slots 自动清理空闲 slot。

九、缓存生效验证

⚠️ 不要再依赖“控制台输出 prompt cache is enabled 即代表正常”——该文案是 TRACE 级日志,默认不打印;且上游整棵树没有 cache hit 这个日志行。开启后只有 --verbose 或日志级别 trace 时才可见,原文字样为 prompt cache is enabled, size limit: N MiB。

可靠验证方法:

  • GET http://127.0.0.1:8080/slots → 查看每个 slot 的 cached / prompt token 数,复用成功时这些数值会保留。
  • 启动加 --verbose,可见 trace 日志:updating prompt cache、saving idle slot to prompt cache、prompt cache is enabled, size limit: N MiB。
  • 最直观的体现:首请求之后,相同前缀请求的 prefill 耗时从几秒降到几十毫秒。

附:配合 Windows 环境变量编辑器“一键配置”时请遵循两条规则——

① 变量名一律用 LLAMA_ARG_ 前缀(如 LLAMA_ARG_CACHE_RAM);布尔取反用 LLAMA_ARG_NO_ 前缀。

② 把旧的 LLAMA_NUM_THREADS 改成 LLAMA_ARG_THREADS;不要加入 LLAMA_ARG_SSD_CACHE / LLAMA_ARG_SSD_CACHE_PATH。

本文所有参数均对照 ggml-org/llama.cpp master(commit 5aeac37,2026-10-18)源码逐条核验。