LMCache 跨引擎 KV Cache 共享实战从 SGLang 写入、vLLM 命中的完整验证方案【免费下载链接】LMCacheLMCache: Supercharge Your LLM with the Fastest KV Cache Layer项目地址: https://gitcode.com/GitHub_Trending/lm/LMCache导读本文基于 LMCache 仓库中的 share_across_engines 示例完整讲解如何在一台双 GPU 机器上让SGLang 计算一次 prompt 的 KV cache 并写入 LMCache 多进程守护进程daemon随后让另一个独立的 vLLM 实例复用这批 KV cache。你将掌握两个引擎的独立虚拟环境安装、LMCache 服务端与两端引擎的启动参数、基于 Prometheus 读计数器和文本一致性双重校验的验证流程以及缓存身份契约模型名、张量并行度、KV dtype、page size、chunk size为什么是跨引擎复用的成败关键。读完本文你可以照搬这套方案在自己的环境上验证一次预填充、多引擎共享的 KV cache 复用收益。适用前提本文所有命令、参数与结论均针对当前仓库中的示例LMCache 0.5.1 SGLang 0.5.15.post1 vLLM 0.25.1 Qwen2.5-32B-Instruct版本固定是为了防止上游发版静默改变行为迁移到其他版本时需重新验证。示例要解决的问题跨引擎 KV cache 复用现代 LLM 服务中同一份 prompt 常常被不同推理引擎重复处理。LMCache 的核心价值之一就是让彼此独立、运行在不同 GPU 上的推理引擎共享已经计算好的 KV cache从而省去重复的 prefill 计算。本示例验证的具体链路是一个 SGLang 实例在 GPU 0 上计算 prompt 的 KV cache并通过 LMCache 集成把结果写入一个 LMCache 多进程守护进程L1 内存池一个 vLLM 实例在 GPU 1 上发出相同 prompt 的请求通过 LMCacheMPConnector 命中并复用 SGLang 写入的 KV cache示例通过LMCache 读计数器lmcache_mp_l1_read_chunks_total证明复用确实发生并通过两个引擎对 prompt 的 tokenize 结果一致来保证缓存键一致一条带cache_salt的缓存隔离冷请求作为正确性参照用于对比 cache-hit 请求的贪婪解码输出。这一方案与仓库中其他 KV cache 复用示例的定位不同local_backends 与 remote_backends 关注同一引擎通过本地/远程存储后端复用自身缓存share_across_instances 关注多个 vLLM 实例之间共享而本示例的独特价值在于SGLang 与 vLLM 两个异构引擎之间的 KV 复用——它要求两者的缓存布局page size、KV 布局、chunk 划分在 LMCache 侧对齐到同一套缓存身份上。环境要求示例在 Linux 上运行对硬件与软件环境有明确约束GPU两块 NVIDIA GPU每块显存至少 80 GB示例实际验证用的是两块 96 GB 的 RTX PRO 6000 Blackwell Server Edition。模型为 32B 规模Qwen2.5-32B-Instruct且 SGLang 与 vLLM 各占一块 GPUCUDA_VISIBLE_DEVICES0/1。PythonPython 3.12包管理使用uv。CPU 内存需要为 LMCache 的 8 GB L1 内存池--l1-size-gb 8预留足够的系统内存。工具curl健康检查与请求发送、setsidverify.sh 启动时会显式检查、awk解析 Prometheus 指标。固定版本2026-07-17 验证组件版本LMCache0.5.1SGLang0.5.15.post1vLLM0.25.1模型Qwen/Qwen2.5-32B-Instructrevision5ede1c97bbab6ce5cda5812749b4c0bdf79b18dd文档明确说明这些版本是验证当天的较新发布固定它们是为了防止后续发版静默改变测试行为。模型 revision 同样被钉死——它是缓存身份的一部分换成其他 revision 会直接导致缓存 miss。安装为两个引擎创建相互隔离的虚拟环境核心原则每个推理引擎只解析它自己的运行时依赖因此要为 SGLang 与 vLLM 分别创建虚拟环境而不是装进同一个环境。LMCache 两个环境都装但各自独立。export UV_CACHE_DIR$PWD/.uv-cache export UV_LINK_MODEcopy uv venv --python 3.12 .venv-sglang uv pip install --prereleaseallow --python .venv-sglang/bin/python \ lmcache0.5.1 sglang0.5.15.post1 uv venv --python 3.12 .venv-vllm uv pip install --python .venv-vllm/bin/python \ lmcache0.5.1 vllm0.25.1几个值得注意的细节--prereleaseallow只用于 SGLang 环境因为 SGLang0.5.15.post1钉了一个预发布版的 FlashAttention wheel不加该选项会安装失败。UV_CACHE_DIR$PWD/.uv-cache把 uv 缓存隔离到本目录避免与其他共享缓存条目相互干扰配合UV_LINK_MODEcopy复制模式而非硬链接兼容 uv 缓存与虚拟环境位于不同文件系统的主机。两个环境都安装lmcache0.5.1因为两端引擎都需要 LMCache 的集成代码SGLang 侧是 sglang_adapter.pyvLLM 侧是 lmcache_mp_connector.py。运行一键脚本 三个进程的编排示例提供了一个端到端脚本 verify.sh在示例目录下直接运行SGLANG_VENV$PWD/.venv-sglang \ VLLM_VENV$PWD/.venv-vllm \ ./verify.sh脚本通过SGLANG_VENV/VLLM_VENV环境变量均带默认值指向示例目录下的.venv-*定位两个环境的解释器LMCACHE_PORT5556、LMCACHE_HTTP_PORT7000、SGLANG_PORT30000、VLLM_PORT8000是默认端口日志写入mktemp创建的临时工作目录。脚本全程set -euo pipefail并在退出时按先 TERM 后 KILL的顺序清理三个进程组cleanup函数 trap cleanup EXIT。第一步启动 LMCache 多进程守护进程setsid ${VLLM_VENV}/bin/lmcache server \ --host 127.0.0.1 \ --port ${LMCACHE_PORT} \ --http-port ${LMCACHE_HTTP_PORT} \ --chunk-size 256 \ --l1-size-gb 8 \ --eviction-policy LRU这是 LMCache 的lmcache server子命令ZMQ HTTP 双端口服务实现在 lmcache/cli/commands/server.py。参数含义--port多进程数据面 ZMQ 端口5556SGLang 与 vLLM 的连接器都通过它读写 KV cache--http-portHTTP 端口7000提供healthcheck健康检查端点和/metricsPrometheus 指标端点——本示例的验证逻辑正是靠读取/metrics里的lmcache_mp_l1_read_chunks_total计数器实现的--chunk-size 256LMCache 以 256 token 为粒度存储/检索 KV cache这是缓存身份契约的一部分SGLang 与 vLLM 两侧必须一致--l1-size-gb 8L1 内存池容量 8 GB对应要求足够 CPU 内存的前提--eviction-policy LRUL1 池的淘汰策略。健康检查使用curl http://127.0.0.1:7000/healthcheck脚本中wait_for_health会以 1 秒间隔轮询、最多 600 次并监控进程是否提前退出。第二步SGLang 写缓存GPU 0CUDA_VISIBLE_DEVICES0 FLASHINFER_USE_CUDA_NORM1 \ ${SGLANG_VENV}/bin/python -m sglang.launch_server \ --model-path Qwen/Qwen2.5-32B-Instruct \ --revision 5ede1c97bbab6ce5cda5812749b4c0bdf79b18dd \ --host 127.0.0.1 --port 30000 \ --tp 1 \ --page-size 16 \ --mem-fraction-static 0.8 \ --disable-cuda-graph \ --enable-lmcache \ --lmcache-config-file ${EXAMPLE_DIR}/lmcache.yamlSGLang 侧的关键是--enable-lmcache--lmcache-config-file。lmcache.yaml 内容极简只声明守护进程地址mp_host: 127.0.0.1 mp_port: 5556它由 sglang_adapter.py 中的init_lmcache_engine读取先通过lmcache_get_config解析成LMCacheEngineConfig再依据模型配置构造 KV 形状num_layer, 2, chunk_size, num_kv_head, head_dimMLA 模型则走num_layer, 1, chunk_size, 1, kv_head_dim分支并以model_path、world_sizetp_size、kv_dtype、kv_shape等构建LMCacheMetadata最终创建 LMCache 引擎。运行中LMCacheConnector.store_kv/load_kv通过token_ids slot_mapping offset与 LMCache 引擎交互把 SGLang 计算出的 KV 按 chunk 写入。FLASHINFER_USE_CUDA_NORM1是文档特别说明的一个环境变量让 FlashInfer0.6.12在验证用的 Blackwell 主机上使用 CUDA JIT 归一化回退路径而不是 CuTeDSL 路径——这是宿主机相关的运行时调优其他架构主机不一定需要。第三步vLLM 读缓存GPU 1CUDA_VISIBLE_DEVICES1 ${VLLM_VENV}/bin/vllm serve Qwen/Qwen2.5-32B-Instruct \ --revision 5ede1c97bbab6ce5cda5812749b4c0bdf79b18dd \ --host 127.0.0.1 --port 8000 \ --tensor-parallel-size 1 \ --block-size 16 \ --gpu-memory-utilization 0.8 \ --no-enable-prefix-caching \ --enforce-eager \ --kv-transfer-config \ {kv_connector:LMCacheMPConnector,kv_connector_module_path:lmcache.integration.vllm.lmcache_mp_connector,kv_role:kv_both,kv_connector_extra_config:{lmcache.mp.host:tcp://127.0.0.1,lmcache.mp.port:5556}}vLLM 侧通过--kv-transfer-config传入 JSON 启用 LMCacheMPConnector这是 vLLM 标准的 KV 传输扩展点kv_connector: LMCacheMPConnector、kv_connector_module_path: lmcache.integration.vllm.lmcache_mp_connector指定使用 LMCache 多进程连接器实现在 lmcache_mp_connector.pykv_role: kv_both本实例同时承担写入与读取角色kv_connector_extra_config.lmcache.mp.host / .lmcache.mp.port指向 LMCache 守护进程的 ZMQ 地址tcp://127.0.0.1:5556。从 LMCacheMPConnector 的类文档 可以看到该连接器支持的扩展配置项除了本示例用到的单服务器lmcache.mp.host/lmcache.mp.port外还包括多服务器部署的lmcache.mp.server_urls、消息队列超时lmcache.mp.mq_timeout、心跳间隔lmcache.mp.heartbeat_interval、请求进入等待队列即提交查找的lmcache.mp.eager_prefetch默认关闭、延迟卸载lmcache.mp.lazy_offload等。连接器在初始化时会做多项布局校验validate_kv_cache_groups、validate_mamba_step_alignment、validate_dcp_support并强制LMCache chunk size 必须是每个缓存组 page chunk 的整数倍这正是示例中两端 page size 必须一致的底层原因。第四步三条请求 判定逻辑脚本依次发送三条/v1/completions请求冷参考请求cache-isolated带cache_salt: cold-reference的 vLLM 请求。cache_salt使缓存键与正式请求不同保证是必然 miss 的缓存隔离请求作为正确性参照SGLang 填充请求向 SGLang 发正式 prompt让其计算 KV 并写入 LMCachevLLM cache-hit 请求向 vLLM 发同一 prompt验证命中 SGLang 写入的缓存。验证脚本在冷请求前后、hit 请求前后分别调用metric_sum lmcache_mp_l1_read_chunks_total读取 Prometheus 计数器awk精确匹配指标名并求和支持带标签的指标行。最终PASS需要同时满足三个条件tokenize 一致SGLang 与两个 vLLM 请求的usage.prompt_tokens完全相同示例中均为 3,688证明缓存键一致确有读取LMCache daemon 在 SGLang 填充之后、vLLM hit 请求期间报告了1 个以上 L1 chunk 读取读计数增量为正同时冷参考请求的读增量为 0——从指标上证明跨引擎复用真实发生输出一致贪婪解码temperature: 0下冷 vLLM 请求与 cache-hit vLLM 请求生成文本完全相同。共享的 prompt 与缓存键示例请求的 prompt 是 160 次拼接的句子 一句指令verify.sh 中生成并写入request.json/cold-request.jsonLMCache lets independent inference engines reuse previously computed key and value tensors for a shared prompt while preserving the model output. 重复 160 次 State the main idea in one sentence.max_tokens: 16、temperature: 0保证解码可复现。由于 LMCache只存储和检索完整的 256-token chunk3,688 个 prompt token 中只有 3,584 个恰好 14 个 chunk进入共享末尾不足一个 chunk 的 token 由 vLLM 自行计算。缓存身份契约为什么只改一端参数会失败文档用一整节强调固定模型 revision、完全相同的模型名、张量并行度、KV dtype、page size 和 LMCache chunk size是缓存身份与布局契约的组成部分。不要只修改其中一个引擎的值。从源码可以印证这一契约的机械性在 sglang_adapter.py 中LMCache 元数据由model_path、world_size、kv_dtype、kv_shape由num_hidden_layers、chunk_size、num_kv_head、head_dim决定等字段构成缓存身份在 lmcache_mp_connector.py 中连接器同样以模型名含 DCP 布局装饰、vllm_block_size由 vLLM 的 block size 推导与 LMCache chunk size 的整除关系来对齐布局并显式校验lmcache_tokens_per_chunk % tokens_per_block 0。因此示例中 SGLang 的--page-size 16与 vLLM 的--block-size 16必须相等、--tp 1与--tensor-parallel-size 1必须一致、两侧 KV dtype 相同chunk size 统一为 256——任何一侧单独改动都会导致缓存键或张量布局不匹配表现为缓存 miss 甚至布局错误。干净环境验证排除碰巧能用的偶然性为证明示例不依赖任何 editable checkout 或旧环境残留的包作者在 2026-07-17 做了两次独立测试第二次运行前删除两个虚拟环境和运行专用的 uv 包缓存从空目录重新创建。两次结果完全一致运行Prompt tokensSGLang 存储 tokensvLLM L1 读取 chunks正确性初始干净安装3,6883,58414冷请求与 cache-hit 的 vLLM 文本一致重建环境后3,6883,58414冷请求与 cache-hit 的 vLLM 文本一致两次运行中带盐的冷参考请求均读取 0 个 L1 chunkcache-hit 的 vLLM 请求两次都生成相同的输出文本。这组数据同时也验证了数值自洽3,584 14 × 256即共享的 KV 恰好是 14 个完整 chunk。在仓库中继续深入如果你想进一步理解或复现本示例背后的机制建议从以下仓库路径入手examples/kv_cache_reuse/share_across_engines/verify.sh端到端编排脚本含全部启动参数、请求构造与断言逻辑examples/kv_cache_reuse/share_across_engines/lmcache.yamlSGLang 侧指向守护进程的极简配置lmcache/integration/sglang/sglang_adapter.pySGLang 集成init_lmcache_engine构建元数据、LMCacheConnector执行 store/loadlmcache/integration/vllm/lmcache_mp_connector.pyvLLM 多进程连接器负责布局校验、缓存身份对齐与异步读写lmcache/cli/commands/server.pylmcache server命令入口组合多进程、存储管理、HTTP 前端与可观测性参数。同目录下的 kv_cache_reuse 总览 还给出了本地/远程存储后端、跨 vLLM 实例等相邻场景可与本示例对照理解 LMCache 在不同共享拓扑下的用法。小结本示例提供了一条可复制、可自证有指标、有文本比对、有干净环境复测的跨引擎 KV 复用路径SGLang 计算并写入 → LMCache 多进程守护进程按 256-token chunk 存储 → vLLM 通过 LMCacheMPConnector 命中复用。实践中务必牢记两点一是两侧引擎的缓存身份契约模型名与 revision、tp 大小、KV dtype、page size、chunk size必须严格对齐二是用cache_salt构造缓存隔离的冷参考请求才能把确实命中了缓存与只是凑巧输出一致严格区分开——这也是 verify.sh 的判定逻辑如此设计的原因。【免费下载链接】LMCacheLMCache: Supercharge Your LLM with the Fastest KV Cache Layer项目地址: https://gitcode.com/GitHub_Trending/lm/LMCache创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考