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
--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 卸载
LLAMA_SSD=1 编译开关,src/llama.cpp 无磁盘溢出逻辑,也无 LLAMA_ARG_SSD_CACHE* 参数。任何中文博客讲的“编译开启 SSD 缓存”都是以讹传讹,加了只会被忽略或报错。
真正可用、且上游确实存在的长上下文手段:
- KV 量化(所有模式通用)—— 见第五节。
- KV 设备级卸载:
--kv-offload/--no-kv-offload(-kvo,默认开启)→LLAMA_ARG_KV_OFFLOAD。把 KV cache 放到另一后端(第二块 GPU / CPU),不是磁盘。多卡 / 异构机器才有意义。 - Context checkpoints:
--ctx-checkpoints N(默认 32)、--checkpoint-min-step(默认 8192)→LLAMA_ARG_CTX_CHECKPOINTS/LLAMA_ARG_CHECKPOINT_MIN_SPACING_NT。在 slot 内保存多个上下文检查点,配合 slot save 一起持久化,适合长文档断点续读。 - Context shift:
--context-shift(无限生成默认开启)。上下文超长时自动移位避免 OOM。
-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
八、常见问题
- 缓存不生效,每次都完整 prefill
- server 确认
--cache-prompt已开(默认开);decision model 需显式--cache-ram N。 - 前缀复用靠 unified KV + prompt caching;
--cache-reuse只影响 KV-shifting 复用、默认 0,不会让前缀复用失效。 - 前缀 token 必须 ≥ 某长度才会复用——这由 unified KV 的前缀匹配决定,不是
cache-reuse阈值。
- server 确认
- slot 保存 API 找不到
- 必须配置
--slot-save-path且目录已存在,否则返回不支持的提示。
- 必须配置
- 配置 SSD 缓存报错
- 该功能根本不存在,任何
LLAMA_SSD*/LLAMA_ARG_SSD_CACHE*都会被忽略或报错,直接删掉即可。
- 该功能根本不存在,任何
- 内存占用持续上涨
- 调低
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 耗时从几秒降到几十毫秒。