LMCache 配置实战:从 3 分钟跑通到多级缓存与分离式预填充
【免费下载链接】LMCacheLMCache: Supercharge Your LLM with the Fastest KV Cache Layer项目地址: https://gitcode.com/GitHub_Trending/lm/LMCache
LMCache 是面向 LLM 推理的 KV 缓存层,用来减少重复的预填充计算、降低长上下文场景的时延与成本。下面按场景拆解 LMCache 配置:多级存储、跨实例共享、分离式预填充和缓存融合,从最小配置开始,配合速查表与排错方法,拿到一份可参考的落地清单。
🚀 最小可用配置:3 分钟跑通本地 CPU 缓存
如果你的目标只是先验证 LMCache 能挂到推理引擎上并产生命中,那么只需要一个本地 CPU 缓存。把下面这段保存为example.yaml,再通过LMCACHE_CONFIG_FILE指向它即可启动:
# example.yaml chunk_size: 256 # 每个缓存块 256 token,前缀复用的最小粒度 local_device: "cpu" local_cpu: True # 启用本地 CPU 缓存 max_local_cpu_size: 10 # CPU 缓存上限 10GB两个要点:
chunk_size决定前缀匹配的粒度,256 是默认值,绝大多数场景不用动;- 配置文件存在时,
LMCACHE_前缀的环境变量会被忽略,所以别在两套机制里混着写。
参考仓库里的 examples/cache_with_configs/ 目录,里面有配套的启动命令和带 tag 的请求示例,可以照着跑一遍。
🗂️ 多级存储分层:CPU、磁盘与远程后端
当模型 KV 体积超出单机 CPU 内存、又希望冷数据不丢失时,按"热在 CPU、温在磁盘、冷在远程"分层是最常见的做法。
local_cpu: True max_local_cpu_size: 20 # 热层:20GB CPU 内存 local_disk: "file:///data/lmcache/disk" # 温层:本地磁盘 max_local_disk_size: 100 # 磁盘层上限 100GB remote_url: "mooncakestore://cache-server:6379" # 冷层:远程存储 remote_serde: "cachegen" # 远程数据用 cachegen 压缩后再存几个容易踩的点:
local_disk必须带file:///前缀,也可以写成逗号分隔的多个路径做多盘并行;- 磁盘吞吐不理想时,可在
extra_config里设use_odirect: true绕过内核页缓存,并用disk_io_threads提高 NVMe 上的并行度; - 有了 NVMe 直读条件的话,还可以启用 GDS(
gds_path、gds_buffer_size),让 GPU 直接读写闪存。
验证方式:发一段重复前缀的请求,观察第二次响应里 LMCache 记录的命中 token 数是否稳定增长。
🎯 淘汰策略与内存细节:命中率不够先查这里
cache_policy决定缓存块满之后淘汰谁,取值有 LRU、LFU、FIFO,默认 LRU:
- 多轮对话、访问局部性好:保持 LRU 即可;
- 热点非常稳定、少数长文反复被引用:LFU 更贴合;
- 一次性批处理、不需要复用:FIFO 实现最简单。
内存层面还有两个值得留意的开关。多路 CPU 的机器上,NUMA 感知分配能明显提升 GPU-CPU 搬运带宽:
numa_mode: "manual" extra_config: gpu_to_numa_mapping: {0: 0, 1: 1} # GPU0 绑定 NUMA0,GPU1 绑定 NUMA1另外,priority_limit可以只缓存优先级不超过某个值的请求(比如priority_limit: 5),让在线关键流量优先占用缓存空间;而save_unfull_chunk: false(默认即是)避免未凑满一个 chunk 的尾部数据占用容量。
🤝 跨实例共享:让多个推理实例互相借用缓存
单机的缓存再大也是孤立的。当你有多个 vLLM 实例、请求路由在不同实例间漂移时,P2P 共享能避免"同一个前缀在每台机器上各存一份、各自重算一遍"。P2P 依赖 controller 做全局元数据协调,配置如下(来自 p2p_sharing 示例):
enable_p2p: True p2p_host: "localhost" p2p_init_ports: 8200 # 实例间建链端口 p2p_lookup_ports: 8201 # 缓存查询端口 transfer_channel: "nixl" # 用 NIXL 做块间数据传输 # controller:P2P 的前置依赖 enable_controller: True lmcache_instance_id: "lmcache_instance_1" controller_pull_url: "localhost:8300" controller_reply_url: "localhost:8400" lmcache_worker_ports: 8500注意每台实例的lmcache_instance_id与端口必须互不相同,否则节点发现会打架。跑起来后,用一台实例生成过的前缀去请求另一台实例,确认能产生跨实例命中。
⚡ 分离式预填充:prefill 和 decode 拆到两台机器
超长提示词(几十万 token)会让单机的 TTFT 很难看。把 prefill 和 decode 拆到不同节点、用 NIXL 通道直传 KV,是 LMCache 应对这个问题的方案,完整部署模板见 examples/disagg_prefill/。
prefiller(发送端)的最小配置:
enable_pd: True transfer_channel: "nixl" pd_role: "sender" # prefill 端;decode 端填 receiver pd_buffer_size: 1073741824 # 1GB 传输缓冲,上限对齐到 chunk pd_buffer_device: "cuda" # 缓冲放 GPU 显存 nixl_backends: ["UCX"]三条硬约束,写配置前先记住:
- 开启 PD 时
remote_url必须留空,save_decode_cache与enable_p2p必须为 false,互斥; - 缓冲大小要覆盖最长 prefill,经验公式:
pd_buffer_size >= (pd_max_prefill_len // chunk_size + 1) * 每 token KV 字节数; - receiver 端还要配置
pd_peer_host、pd_peer_init_port、pd_peer_alloc_port来绑定监听。
验证方式:长提示词请求的 TTFT 应显著低于同机不拆分的情况,且 proxy 端日志能看到传输完成事件。
🧬 缓存融合:拼接不同请求的 KV 片段
当多个请求各自命中了一部分缓存、但整段前缀都对不上时,blend 会把已命中的块拼进本次计算、只对差异部分重算,省下的就是重算量:
enable_blending: True blend_recompute_ratios: 0.15 # 约 15% 的 token 需要重算以保证精度 blend_check_layers: 1 # 用前 1 层判断哪些 token 要重算 blend_special_str: " # # " # 片段分隔符注意 blend 通常要和use_layerwise: True搭配使用,示例脚本见 examples/blend_in_process/。重算比例是精度与收益的权衡,拿不准就先保持 0.15。
🔧 调优与排错:现象 → 原因 → 处理
现象:命中率上不去,重复前缀仍大量重算。原因:
chunk_size与请求长度错位,或前缀只命中零散几块。处理:对齐chunk_size(256/512/1024);命中过于碎片时启用 blend;也可用min_retrieve_tokens跳过命中太少不值得取回的请求。现象:CPU 内存占用高,甚至挤占系统余量。原因:
max_local_cpu_size给大了,或缓存了无复用价值的块。处理:调小容量上限;确认save_unfull_chunk为 false;用store_location指定只写目标后端;再预留reserve_local_cpu_size给系统。现象:CPU 缓存开到百 GB 级别时进程启动特别慢。原因:启动即全量分配内存。处理:开启
enable_lazy_memory_allocator: True,从lazy_memory_initial_ratio(默认 0.2)起步按需扩容。现象:磁盘层读速不达预期。原因:走了内核页缓存、或 I/O 线程不够。处理:
extra_config里设use_odirect: true、disk_io_threads: 8,NVMe 环境优先 GDS 后端。现象:P2P 节点间时而同步超时、查不到对方缓存。原因:端口未对齐、网络 MTU 不一致、NIXL 传输后端不匹配。处理:核对各实例端口与
p2p_host;确认nixl_backends(默认 UCX)与链路能力匹配;必要时在extra_config里调p2p_socket_recv_timeout_ms/p2p_socket_send_timeout_ms。
📋 参数速查表
| 参数 | 环境变量 | 默认值 | 何时需要调整 |
|---|---|---|---|
| chunk_size | LMCACHE_CHUNK_SIZE | 256 | 请求普遍很长/很短、命中率异常时 |
| local_cpu | LMCACHE_LOCAL_CPU | true | 明确不想占用 CPU 内存时关闭 |
| max_local_cpu_size | LMCACHE_MAX_LOCAL_CPU_SIZE | 5.0 | 按机器内存决定缓存容量 |
| local_disk | LMCACHE_LOCAL_DISK | 空 | 需要磁盘温层时 |
| max_local_disk_size | LMCACHE_MAX_LOCAL_DISK_SIZE | 0.0 | 与 local_disk 配套设置上限 |
| remote_url | LMCACHE_REMOTE_URL | 空 | 需要跨机远程存储时 |
| remote_serde | LMCACHE_REMOTE_SERDE | naive | 远程带宽紧张时改 cachegen |
| cache_policy | LMCACHE_CACHE_POLICY | LRU | 访问模式偏热点/顺序时换 LFU/FIFO |
| save_unfull_chunk | LMCACHE_SAVE_UNFULL_CHUNK | false | 一般不动 |
| numa_mode | LMCACHE_NUMA_MODE | null | 多路 CPU 机器优化搬运带宽 |
| enable_pd / pd_role | LMCACHE_ENABLE_PD / LMCACHE_PD_ROLE | false / - | 做 prefill-decode 拆分时 |
| pd_buffer_size / pd_buffer_device | LMCACHE_PD_BUFFER_SIZE / _DEVICE | 必填 | 开 PD 时按最长 prefill 估算 |
| enable_blending | LMCACHE_ENABLE_BLENDING | false | 前缀零散命中、想省重算时 |
| blend_recompute_ratios | LMCACHE_BLEND_RECOMPUTE_RATIOS | 0.15 | 精度与收益之间取舍 |
| enable_p2p | LMCACHE_ENABLE_P2P | false | 多实例间共享缓存时 |
| internal_api_server_enabled / port_start | LMCACHE_INTERNAL_API_SERVER_ENABLED / _PORT_START | false / 6999 | 需要运行时看指标、调日志级别时 |
更完整的参数说明(含 lazy 内存分配器、GDS、NIXL 存储后端、Prometheus 直方图桶等)见 docs/source/api_reference/configurations.rst。
从最小配置开始,跑通命中之后再按你的实际负载逐层加:先分层存储,再考虑跨实例共享或 PD 拆分,每次只改一处、用命中率与 TTFT 数据说话。需要深入某一模式时,docs/source/mp/ 下的 MP 模式文档和 examples/ 里的各场景示例是最直接的对照材料。
【免费下载链接】LMCacheLMCache: Supercharge Your LLM with the Fastest KV Cache Layer项目地址: https://gitcode.com/GitHub_Trending/lm/LMCache
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考