LMCache-Ascend 用户手册 ​

1. 文档说明 ​

LMCache-Ascend 是 LMCache 面向昇腾 NPU 的适配插件,可在 vLLM-Ascend 推理服务之间复用和传输 KV Cache。本手册重点介绍以下两种部署方式:

• 1P1D(Disaggregated Prefill):将 Prefill 和 Decode 部署为不同服务,由 Prefill 实例生成 KV Cache,并传递给 Decode 实例继续生成。

• P2P KV Cache 共享:多个对等 vLLM 实例通过 Controller 发现缓存位置,并经 RoCE 直接拉取其他实例 CPU 内存中的 KV Cache。

2. 部署前准备 ​

2.1 基础软硬件要求 ​

建议在开始部署前确认:

• 至少 2 张昇腾 NPU;若两个实例均采用 TP=2,则至少需要 4 张 NPU;

• 若多级部署,节点之间应有HCCL互联。

• 1P1D 和 P2P 样例要求 Ascend HDK 驱动、固件 25.5.0 或更高版本;

• HCCL/HIXL 传输通道要求 CANN 8.5 或更高版本;

• 已安装版本匹配的 LMCache、LMCache-Ascend、vLLM 和 vLLM-Ascend;vllm安装可参考:

• 模型目录可被各实例访问,且各实例加载相同模型和兼容的模型配置。

当前仓库根目录 README.md 提供了版本兼容矩阵。部署前应以所使用分支或发布版本对应的矩阵为准,不要混用不同发布版本的 LMCache 与 LMCache-Ascend。

2.2 环境软件安装 ​

vLLM-Ascend环境准备可参考官方文档

LMCache安装:NO_CUDA_EXT=1 pip install lmcache==0.4.4

LMCache-Ascend安装:

• 方法一:配置openEuler-26.09-DevStation的软件源后,dnf install -y LMCache-Ascend

• 方法二:从Github上游仓库源码安装:

bash
git clone --recurse-submodules -b v0.4.4 https://github.com/LMCache/LMCache-Ascend.git
cd LMCache-Ascend
pip install -v --no-build-isolation -e .

注意事项:

• 方法一:

• dnf install方法只能向系统自带的Python中安装,因此要求/usr/bin/python3版本为Python 3.11系列。

• vLLM与vLLM-Ascend也要向/usr/bin/python3安装

• 方法二:

• 源码安装不限定Python具体版本,只需要Python >= 3.10。

• 源码安装命令请自行修改,向带有vLLM + vLLM-Ascend的Python环境安装。

3. 通用配置与环境变量 ​

3.1 LMCACHE_CONFIG_FILE ​

该环境变量指定当前 vLLM 实例使用的 LMCache YAML 配置文件。每个实例应指向自己的配置文件,例如:

bash
export LMCACHE_CONFIG_FILE=/workspace/LMCache-Ascend/examples/disagg_prefill/1p1d/configs/lmcache-prefiller-config.yaml

建议使用绝对路径,并在启动前检查文件是否挂载到容器内。

3.2 ASCEND_RT_VISIBLE_DEVICES ​

用于指定当前进程可见的 NPU。例如 TP=2 时:

bash
export ASCEND_RT_VISIBLE_DEVICES=4,5

可见设备数量不得少于 --tensor-parallel-size。同机部署多个实例时,应为各实例分配不重叠的设备集合。

3.3 vLLM 多进程环境变量 ​

bash
export VLLM_ENABLE_V1_MULTIPROCESSING=1
export VLLM_WORKER_MULTIPROC_METHOD=spawn

• VLLM_ENABLE_V1_MULTIPROCESSING=1:启用 vLLM V1 worker 多进程模式。

• VLLM_WORKER_MULTIPROC_METHOD=spawn:使用 spawn 创建 worker,避免在已初始化 NPU 运行时之后 fork 产生不安全状态。

3.4 PYTHONHASHSEED:必须保持一致的哈希种子 ​

Python 默认会在每个解释器进程启动时随机化部分内置对象的哈希结果。LMCache 使用基于 token 序列和前缀哈希的键来标识 KV Cache;若协作进程的哈希种子不同,同一段 token 可能得到不同的缓存键,进而表现为缓存查找失败、跨实例命中率异常或 Controller 与 worker 认知不一致。

因此必须遵守以下规则:

  1. 参与同一缓存域的所有 Python 进程使用完全相同的整数值,包括 Controller、Prefill、Decode 以及所有 P2P vLLM 实例。
  2. 取值本身不是性能参数,0、123 或其他 Python 支持的固定整数均可;关键是所有进程一致。
  3. 不要省略该变量,也不要使用 random。不同部署组可以使用不同值,但同一组中途不得改变。
  4. 修改该值后,应重启该缓存域内的全部相关进程;旧进程产生的内存缓存不应继续与新种子进程混用。

1P1D 样例统一使用:

bash
export PYTHONHASHSEED=0

P2P 样例统一使用:

bash
export PYTHONHASHSEED=123

二者都正确。生产环境可以统一选用 0,并通过容器环境变量、启动脚本或 Pod env 固化。P2P Controller 也必须带相同值启动:

bash
PYTHONHASHSEED=123 lmcache_controller ...

3.5 LMCACHE_TRACK_USAGE:关闭 LMCache 匿名用量统计 ​

LMCache 默认会初始化用量统计上下文,采集匿名运行环境、引擎配置和运行时元数据,并上报到 LMCache 用量统计服务;这些统计不影响 KV Cache 的读写、命中或传输功能。

在内网、离线、隐私合规或不希望产生外部统计请求的部署中,建议为所有 vLLM / LMCache worker 进程显式关闭:

bash
export LMCACHE_TRACK_USAGE=false

注意该变量在 LMCache 中按字符串精确判断,只有小写 false 会关闭统计;未设置或设置为其他值时仍按默认启用处理。关闭后 InitializeUsageContext 返回 None,不会发送或记录用量统计数据。

3.6 常用 vLLM 参数 ​

参数样例值说明与取值建议
--model/data/models/Qwen/Qwen3-8B模型目录。参与 KV 传输或共享的实例应使用相同模型及兼容配置。
--tensor-parallel-size2TP rank 数。必须与配置中的逐 rank 端口列表长度一致。
--block-size128vLLM paged KV block 的 token 数。它不等同于 LMCache 的 chunk_size,应按当前 vLLM-Ascend 支持范围设置。
--max-model-len32768最大上下文长度。调大后可能需要增大传输缓冲区并预留更多 NPU/CPU 内存。
--enforce-eager开启强制 eager 执行,便于样例稳定运行和排障,但可能牺牲图模式带来的性能收益。
--no-enable-prefix-caching1P1D 开启禁用 vLLM 自身 prefix caching,避免与样例中的 LMCache 路径混淆。
--trust-remote-code开启允许执行模型仓库自定义代码;只应对可信模型使用。
--disable-log-requests开启减少请求日志量,不影响 KV Cache 功能。排障时可临时去掉。

4. 1P1D 部署 ​

推理服务启动脚本中的Python命令,请自行替换成装有vLLM + vLLM-Ascend + LMCache + LMCache-Ascend依赖的环境

4.1 架构与请求流 ​

1P1D 包含三个服务:

  1. Proxy 接收客户端请求并协调 Prefill 与 Decode;
  2. Prefill 实例完成提示词预填充并生成 KV Cache;
  3. Decode 实例接收 KV Cache,从约定位置继续生成 token。

样例端口关系如下:

组件端口/端口组用途
Prefill API7100Prefill OpenAI API 服务
Decode API7200Decode OpenAI API 服务
Proxy API9100客户端访问入口
Decode init7300,7301每个 TP rank 一个初始化端口
Decode alloc7400,7401每个 TP rank 一个内存分配端口
PD proxy7500Prefill/Decode 协调端口
Pull done7600,7601每个 TP rank 一个完成通知端口

4.2 Prefill 配置 ​

样例文件:examples/disagg_prefill/1p1d/configs/lmcache-prefiller-config.yaml。

yaml
local_cpu: False

enable_pd: True
transfer_channel: "hccl"
pd_role: "sender"
pd_pull_mode: False
pd_delay_pull: False
pd_pull_done_port: [7600, 7601]
pd_use_cpu_offload: False
pd_cpu_buffer_size: 21474836480
pd_peer_host: "localhost"
pd_proxy_host: "localhost"
pd_proxy_port: 7500
pd_buffer_size: 2415919104
pd_buffer_device: "npu"

save_unfull_chunk: True

关键参数说明:

参数说明
local_cpu是否启用常规本地 CPU KV 缓存。本例关闭,PD 传输缓冲区由专用参数管理。
enable_pd启用 Prefill/Decode 分离传输后端,两端都必须为 True。
pd_rolePrefill 固定为 sender;Decode 固定为 receiver。
transfer_channelhccl 为推荐值;hixl 为实验特性。两端必须选择兼容的通道。
pd_pull_modeFalse 表示不使用接收端按需拉取模式。本样例采用该设置。
pd_delay_pull延迟到消费 KV 时再拉取,仅在 pull mode 且使用 NPU 缓冲区时有意义;本例关闭。
pd_pull_done_portpull mode 下 sender 接收完成信号的端口列表,每个 TP rank 一个。虽然样例当前关闭 pull mode,仍预留了端口。
pd_use_cpu_offloadsender 是否先将 KV 从 NPU 卸载到 CPU,再供远端读取。仅 sender pull mode 路径使用。
pd_cpu_buffer_sizeCPU offload 缓冲区字节数。本例为 21474836480,即 20 GiB;仅启用 CPU offload 路径时实际使用。
pd_peer_host对端可达地址。多机时填写对应节点的 RoCE 网络 IP。
pd_proxy_host / pd_proxy_port协调代理地址和端口,应与 proxy 启动参数一致。
pd_buffer_sizePD 传输缓冲区字节数。本例 sender 为 2415919104,即 2.25 GiB。实现会按单个 KV 对象大小向上对齐,实际分配可能略大。
pd_buffer_devicenpu 表示传输缓冲区位于 NPU;也可按受支持路径使用 cpu。NPU 缓冲区更直接,但会占用显存。
save_unfull_chunk保存不足一个完整 LMCache chunk 的尾部 KV,使短 prompt 也能发生 PD 传输。关闭时尾部不足整块的 KV 可能不被保存。

4.3 Decode 配置 ​

样例文件:examples/disagg_prefill/1p1d/configs/lmcache-decoder-config.yaml。

yaml
local_cpu: False

enable_pd: True
transfer_channel: "hccl"
pd_role: "receiver"
pd_peer_host: "localhost"
pd_pull_mode: False
pd_delay_pull: False
pd_peer_init_port: [7300, 7301]
pd_peer_alloc_port: [7400, 7401]
pd_buffer_size: 134217728
pd_buffer_device: "npu"

其中:

• pd_peer_init_port:接收端每个 TP rank 的传输初始化端口;

• pd_peer_alloc_port:接收端每个 TP rank 的内存分配通信端口;

• 两个列表长度均需等于 TP 大小;

• pd_buffer_size: 134217728 为 128 MiB。该空间位于 pd_buffer_device 指定的设备上,需结合最大命中长度和并发量调优。

pd_buffer_size 越大,可承载的在途 KV 数据越多,但内存占用也越高。估算时不能只用 token 数乘 dtype 字节数,而应计入所有层、K/V 张量、KV head 和 head dimension。建议先以样例值验证,再根据最长 prompt、并发量、模型 KV 形状和运行日志逐步调整。

4.4 启动 Prefill 服务 ​

bash
export LMCACHE_CONFIG_FILE=/workspace/LMCache-Ascend/examples/disagg_prefill/1p1d/configs/lmcache-prefiller-config.yaml
export ASCEND_RT_VISIBLE_DEVICES=4,5
export VLLM_ENABLE_V1_MULTIPROCESSING=1
export VLLM_WORKER_MULTIPROC_METHOD=spawn
export PYTHONHASHSEED=0

python -m vllm.entrypoints.openai.api_server \
  --port 7100 \
  --model /data/models/Qwen/Qwen3-8B \
  --enforce-eager \
  --no-enable-prefix-caching \
  --tensor-parallel-size 2 \
  --trust-remote-code \
  --disable-log-requests \
  --block-size 128 \
  --max-model-len 32768 \
  --kv-transfer-config '{"kv_connector":"LMCacheAscendConnector","kv_role":"kv_producer","kv_connector_extra_config":{"discard_partial_chunks":false,"lmcache_rpc_port":"producer1"}}' \
  > prefill.txt 2>&1

kv-transfer-config 中:

• kv_connector:使用 LMCache-Ascend connector;

• kv_role: kv_producer:声明该实例是 KV 生产者;

• discard_partial_chunks: false:保留不完整 chunk,与 save_unfull_chunk: True 配合,改善短 prompt 或尾块传输;

• lmcache_rpc_port: producer1:当前实例内部 LMCache RPC 标识,需与其他实例区分。该字段虽名为 port,样例使用字符串标识。

4.5 启动 Decode 服务 ​

bash
export LMCACHE_CONFIG_FILE=/workspace/LMCache-Ascend/examples/disagg_prefill/1p1d/configs/lmcache-decoder-config.yaml
export ASCEND_RT_VISIBLE_DEVICES=6,7
export VLLM_ENABLE_V1_MULTIPROCESSING=1
export VLLM_WORKER_MULTIPROC_METHOD=spawn
export PYTHONHASHSEED=0

python -m vllm.entrypoints.openai.api_server \
  --port 7200 \
  --model /data/models/Qwen/Qwen3-8B \
  --enforce-eager \
  --no-enable-prefix-caching \
  --tensor-parallel-size 2 \
  --trust-remote-code \
  --disable-log-requests \
  --block-size 128 \
  --max-model-len 32768 \
  --kv-transfer-config '{"kv_connector":"LMCacheAscendConnector","kv_role":"kv_consumer","kv_connector_extra_config":{"discard_partial_chunks":false,"lmcache_rpc_port":"consumer1","skip_last_n_tokens":1}}' \
  > decode.txt 2>&1

• kv_role: kv_consumer:声明 Decode 为 KV 消费者;

• skip_last_n_tokens: 1:不从 LMCache 加载最后 1 个 token 的 KV,由 Decode 侧计算该 token,以满足分离式调度中继续生成的边界要求;应保持样例值,除非所用 vLLM/LMCache 版本明确要求其他值;

• lmcache_rpc_port: consumer1:必须与 Prefill 的标识不同。

4.6 启动 Proxy ​

bash
python3 /workspace/LMCache/examples/disagg_prefill/disagg_proxy_server.py \
  --host localhost \
  --port 9100 \
  --prefiller-host localhost \
  --prefiller-port 7100 \
  --num-prefillers 1 \
  --decoder-host localhost \
  --decoder-port 7200 \
  --decoder-init-port "7300,7301" \
  --decoder-alloc-port "7400,7401" \
  --proxy-host localhost \
  --proxy-port 7500 \
  --num-decoders 1

建议按 Prefill、Decode、Proxy 的顺序启动,并先确认前两个 API 进程已完成模型加载。多机时,各 host 参数应使用实际可达地址,不能保留 localhost。

4.7 发起验证请求 ​

bash
curl -X POST http://localhost:9100/v1/completions \
  -H "Content-Type: application/json" \
  -d "{
    \"model\": \"/data/models/Qwen/Qwen3-8B\",
    \"prompt\": \"$(printf 'Explain the significance of KV cache in language models in English.%.0s' {1..100})\",
    \"max_tokens\": 100
  }"

验证时同时观察 prefill.txt 和 decode.txt,确认请求经过两个实例且无端口连接、内存注册或 KV 传输错误。

5. P2P KV Cache 共享部署 ​

推理服务启动脚本中的Python命令,请自行替换成装有vLLM + vLLM-Ascend + LMCache + LMCache-Ascend依赖的环境

5.1 架构说明 ​

P2P 模式中的 vLLM 实例均配置为 kv_both,既可生产并保存 KV Cache,也可从其他实例获取 KV Cache。Controller 负责实例注册、缓存位置查询与路由;KV 数据本身通过 P2P 传输通道移动,而非由 Controller 中转。

样例结合了三项能力:

yaml
p2p_pull_mode: True
p2p_delay_pull: True
p2p_use_npu: True

extra_config:
  use_host_staging: True

该组合表示使用 HostStaging 的延迟 rH2D pull:生产端将命中 KV 拷贝到有限大小、已注册的 CPU staging arena;消费端在实际加载 KV 时,通过 RDMA 将微批数据直接拉入两个交替使用的 NPU 缓冲池,并与 KV scatter 重叠。

5.2 P2P 配置样例 ​

实例 1 的核心配置如下:

yaml
chunk_size: 256
local_cpu: True
max_local_cpu_size: 16
enable_async_loading: False

enable_p2p: True
p2p_host: "localhost"
p2p_init_ports: [9960, 9961]
p2p_lookup_ports: [9962, 9963]
transfer_channel: "hccl"
p2p_use_npu: True
p2p_pull_mode: True
p2p_delay_pull: True
p2p_npu_buffer_size: 134217728

enable_controller: True
lmcache_instance_id: "lmcache_instance_1"
controller_pull_url: "localhost:9800"
controller_reply_url: "localhost:9900"
lmcache_worker_ports: [9950, 9951]

extra_config:
  lookup_backoff_time: 0.001
  use_host_staging: True
  os_staging_bytes: 8589934592

实例 2 使用相同的传输策略,但以下字段必须不同:

字段实例 1实例 2
lmcache_instance_idlmcache_instance_1lmcache_instance_2
p2p_init_ports[9960, 9961][9964, 9965]
p2p_lookup_ports[9962, 9963][9966, 9967]
lmcache_worker_ports[9950, 9951][9952, 9953]

5.3 关键参数说明 ​

参数说明与建议
chunk_size每个 LMCache 缓存块包含的 token 数。本例为 256。较大值可降低元数据和查询开销,但会提高尾块浪费,并降低短前缀的复用粒度。所有共享实例应保持一致。
local_cpuP2P 依赖本地 CPU backend 保存可共享 KV,本例必须启用。
max_local_cpu_size每个启用存储的 LMCache worker 的 CPU KV 缓存上限,单位为 GiB。本例为 16。总预算需乘以实际拥有存储的 worker 数。
enable_async_loading是否启用 LMCache 异步加载。默认 False;本例保持关闭,以使用样例已验证的 P2P + HostStaging 延迟 rH2D 路径。
enable_p2p启用 P2P backend。
p2p_host当前实例向其他实例公布的地址。多机部署必须填写其他节点可达的 RoCE 网络 IP,而不是 localhost。
p2p_init_ports各 TP rank 的传输初始化端口,一 rank 一端口。
p2p_lookup_ports各 TP rank 的 P2P 查询端口,一 rank 一端口。
p2p_use_npu启用 NPU 传输缓冲区,使远端 host 数据可被拉入 NPU。
p2p_pull_mode由消费端主动读取生产端数据。HostStaging 要求该值为 True。
p2p_delay_pull查询命中时先返回轻量代理,待 vLLM 实际消费时分微批拉取。要求 p2p_pull_mode=True 且 p2p_use_npu=True;否则无法形成延迟 rH2D 路径。
p2p_npu_buffer_size每个 worker 的 NPU P2P scratch buffer 字节数。本例为 128 MiB。延迟拉取会将内存占用限制在该缓冲池附近;增大可提高微批容量,但会占用更多 NPU 内存。
transfer_channel推荐 hccl。hixl 仍为实验特性,且不支持 HostStaging。
enable_controller开启与 LMCache Controller 的交互。所有实例都应开启。
lmcache_instance_id实例唯一标识。同一 Controller 下不得重复。
controller_pull_urlController pull monitor 地址,与 Controller 的 monitor-ports.pull 对应。
controller_reply_urlController reply monitor 地址,与 Controller 的 monitor-ports.reply 对应。
lmcache_worker_portsController 与各 TP worker 通信的端口,一 rank 一端口,且实例间不可冲突。
lookup_backoff_time异步查询重试间隔,单位为秒;0.001 即 1 ms。过小会增加轮询开销,过大则增加缓存命中等待时延。
use_host_staging只注册有限的 CPU staging arena,而不是完整 CPU KV cache,可降低 HCCL 注册压力,但生产端增加一次 CPU 到 CPU 拷贝。
os_staging_bytes每个 LMCache worker 的 HostStaging arena 容量。本例为 8 GiB;不是每实例或每节点的总量。

enable_async_loading 使用建议 ​

enable_async_loading: True 会将 LMCache 的查询与加载拆成异步路径:scheduler 侧先发送 chunk hash 查询,worker 侧通过异步 lookup server 对后端执行 batched_async_contains,并提前发起非阻塞读取,从而让 KV 拉取与 vLLM 调度/计算尽量重叠。该模式适合远端存储或后端读取延迟较高、且后端已支持异步查询/预取的场景。

重要:若在 P2P 场景同时开启 cache_policy,压测时必须开启 enable_async_loading,否则访问对端缓存可能报错。

配置互斥:P2P 池化与 SSD 多级缓存 ​

当前版本中,P2P 池化路径与 SSD 多级缓存路径同时开启时存在已知问题,建议二选一使用,不要在同一组实例中混配:

  • 使用本文 P2P 共享样例时,保持 SSD / 本地磁盘层关闭,即不要配置 local_disk,并保持 max_local_disk_size 不设置。
  • 如果需要验证 SSD 多级缓存,请关闭 P2P 相关能力,例如 enable_p2p: False,并移除 p2p_*、Controller、HostStaging 等 P2P 配置。
  • 不建议依赖 cache_policy、enable_async_loading 等开关来规避该组合问题;即使部分场景可以绕过报错,也应按互斥配置处理,避免压测或长稳运行中出现不一致行为。

5.4 HostStaging 模式选择 ​

如果 HCCL 能稳定注册完整 CPU KV cache,建议设置:

yaml
extra_config:
  use_host_staging: False

这能避免生产端额外 staging 拷贝。大模型场景中,完整缓存注册可能耗尽 Device OS 内存,并可能出现错误码 19。此时可开启 HostStaging,并在 $HOME/ascend/log 下的 Ascend PLOG 中确认底层注册错误。

HostStaging 支持矩阵如下:

模式p2p_pull_modep2p_delay_pullp2p_use_npu结果
延迟 rH2D pullTrueTrueTrue支持,样例推荐组合
eager CPU pullTrueFalseFalse支持,数据先物化为 CPU KV 对象
eager NPU pullTrueFalseTrueHostStaging 不支持,启动时拒绝
push modeFalse任意任意HostStaging 不支持,启动时拒绝

若 p2p_delay_pull=True 但 p2p_use_npu=False,实现会发出警告并关闭 delayed pull。此时应显式配置 eager CPU pull,避免配置含义不清。

5.5 os_staging_bytes 容量估算 ​

可用以下公式估算每个 TP rank 所需容量:

text
os_staging_bytes ≈ concurrent_requests_per_rank
                   × hit_tokens_per_request
                   × KV_bytes_per_token_per_rank

其中:

• concurrent_requests_per_rank 是已经 staging、但尚未收到 Done 的并发命中请求数;

• hit_tokens_per_request 建议使用 p95 或最大预期缓存命中长度;

• KV_bytes_per_token_per_rank 必须包含该 rank 上所有层、K/V、KV heads、head dimension 与 dtype 的总字节数。

arena 会向下取整为完整且对齐的 KV chunk,并且至少能容纳一个 chunk。若无法容纳完整命中,LMCache 只提供能够放入 arena 的前缀,剩余 token 将重新计算。

总主机内存必须按 worker 累加。例如两个 TP=2 实例均在所有 rank 开启存储,8 GiB staging 加 16 GiB CPU cache 的理论预算为:

text
4 workers × (8 GiB + 16 GiB) = 96 GiB

该数值还不包括模型服务、Python 进程和系统本身的内存。

对于 MLA/DSA 且启用 save_only_first_rank: True 的场景,建议使用 eager HostStaging CPU pull:

yaml
p2p_pull_mode: True
p2p_delay_pull: False
p2p_use_npu: False

extra_config:
  save_only_first_rank: True
  use_host_staging: True
  os_staging_bytes: 8589934592

此时仅第一个 rank 持有并从存储后端读取 KV,再向其他 rank 广播;物化后的 CPU KV 对象更适合该流程。

5.6 启动 Controller ​

bash
PYTHONHASHSEED=123 lmcache_controller \
  --host 0.0.0.0 \
  --port 9000 \
  --monitor-ports '{"pull":9800,"reply":9900}'

Controller 的 9800 和 9900 必须与两个实例 YAML 中的 controller_pull_url 和 controller_reply_url 对应。多机时,实例配置中的主机名应替换为 Controller 的可达 IP。

5.7 启动两个 P2P 实例 ​

实例 1:

bash
export LMCACHE_CONFIG_FILE=/workspace/LMCache-Ascend/examples/kv_cache_reuse/share_across_instances/p2p_sharing/instance1.yaml
export ASCEND_RT_VISIBLE_DEVICES=2,3
export VLLM_ENABLE_V1_MULTIPROCESSING=1
export VLLM_WORKER_MULTIPROC_METHOD=spawn
export PYTHONHASHSEED=123
export LMCACHE_TRACK_USAGE=false

python -m vllm.entrypoints.openai.api_server \
  --port 8010 \
  --model /data/models/Qwen/Qwen3-8B \
  --enforce-eager \
  --tensor-parallel-size 2 \
  --trust-remote-code \
  --disable-log-requests \
  --block-size 128 \
  --rope-scaling '{"rope_type":"yarn","factor":4.0,"original_max_position_embeddings":32768}' \
  --max-model-len 32768 \
  --kv-transfer-config '{"kv_connector":"LMCacheAscendConnector","kv_role":"kv_both"}' \
  > instance1.txt 2>&1

实例 2:

bash
export LMCACHE_CONFIG_FILE=/workspace/LMCache-Ascend/examples/kv_cache_reuse/share_across_instances/p2p_sharing/instance2.yaml
export ASCEND_RT_VISIBLE_DEVICES=6,7
export VLLM_ENABLE_V1_MULTIPROCESSING=1
export VLLM_WORKER_MULTIPROC_METHOD=spawn
export PYTHONHASHSEED=123
export LMCACHE_TRACK_USAGE=false

python -m vllm.entrypoints.openai.api_server \
  --port 8011 \
  --model /data/models/Qwen/Qwen3-8B \
  --enforce-eager \
  --tensor-parallel-size 2 \
  --trust-remote-code \
  --disable-log-requests \
  --block-size 128 \
  --rope-scaling '{"rope_type":"yarn","factor":4.0,"original_max_position_embeddings":32768}' \
  --max-model-len 32768 \
  --kv-transfer-config '{"kv_connector":"LMCacheAscendConnector","kv_role":"kv_both"}' \
  > instance2.txt 2>&1

kv_role: kv_both 表示实例既可将 KV 写入本地缓存并对外提供,也可从远端实例读取命中的 KV。

--rope-scaling 是本模型样例的上下文扩展配置,并非 LMCache P2P 的必需开关。更换模型时应按模型自身配置决定是否保留,错误的 RoPE 参数会影响模型输出质量。

5.8 验证跨实例命中 ​

先向实例 1 发送长 prompt,使其填充缓存:

bash
time curl -X POST http://localhost:8010/v1/completions \
  -H "Content-Type: application/json" \
  -d "{
    \"model\": \"/data/models/Qwen/Qwen3-8B\",
    \"prompt\": \"$(printf 'Explain the significance of KV cache in language models in English.%.0s' {1..1000})\",
    \"max_tokens\": 10,
    \"temperature\": 0
  }"

再将完全相同的 prompt 发送到实例 2:

bash
time curl -X POST http://localhost:8011/v1/completions \
  -H "Content-Type: application/json" \
  -d "{
    \"model\": \"/data/models/Qwen/Qwen3-8B\",
    \"prompt\": \"$(printf 'Explain the significance of KV cache in language models in English.%.0s' {1..1000})\",
    \"max_tokens\": 10,
    \"temperature\": 0
  }"

实例 2 日志应出现类似信息:

text
LMCache INFO: Retrieved 1002 out of total 1002 tokens. size: 0.1223 gb, cost 60.3595 ms, throughput: 2.0264 GB/s

命中 token 数和吞吐量会随 tokenizer、软件版本、模型、网络及机器负载变化,不应将样例数值作为性能承诺。

6. 参数一致性检查表 ​

6.1 所有协作进程必须一致 ​

• PYTHONHASHSEED;

• 模型及影响 KV 形状的模型配置;

• chunk_size;

• 兼容的 transfer_channel;

• vLLM --block-size 和其他影响运行时布局的关键参数;

• 软件版本与补丁状态。

6.2 必须唯一或避免冲突 ​

• 每个 P2P 实例的 lmcache_instance_id;

• vLLM API 端口;

• p2p_init_ports、p2p_lookup_ports、lmcache_worker_ports;

• 1P1D 中的 Prefill/Decode API 端口和 TP 通信端口;

• 同机各实例使用的 NPU 设备集合。

6.3 必须与 TP 大小匹配 ​

• pd_peer_init_port;

• pd_peer_alloc_port;

• pd_pull_done_port;

• p2p_init_ports;

• p2p_lookup_ports;

• lmcache_worker_ports。

例如 --tensor-parallel-size 2 时,上述已启用的端口列表应各包含两个端口。

7. 常见问题与排障 ​

7.1 相同 prompt 无法跨实例命中 ​

依次检查:

  1. Controller、全部 vLLM 实例的 PYTHONHASHSEED 是否已设置且完全相同;
  2. prompt 是否逐字节相同,包括空格、模板和 tokenizer 处理;
  3. 两个实例的模型、tokenizer、chunk_size 是否一致;
  4. lmcache_instance_id 是否唯一;
  5. Controller URL 和 worker/P2P 端口是否可达;
  6. 实例 1 是否确实完成缓存写入后,实例 2 才发起请求。

7.2 启动时端口绑定失败 ​

• 使用 ss -lntp 检查端口占用;

• 确认两个 P2P YAML 没有复用逐 rank 端口;

• 确认端口列表长度与 TP 大小一致;

• 多机部署时检查监听地址、防火墙和容器网络模式。

7.3 NPU 或主机内存不足 ​

• 减小 pd_buffer_size 或 p2p_npu_buffer_size;

• 减小 max_local_cpu_size 或 os_staging_bytes;

• 注意这些容量通常按 worker/TP rank 分配,而非按实例只分配一次;

• 适当降低 --max-model-len、并发数或 vLLM NPU 内存利用率;

• 修改后检查是否仍至少容纳一个完整 KV chunk。

7.4 HCCL 注册失败或出现错误码 19 ​

• 查看 $HOME/ascend/log 下的 PLOG;

• 确认驱动、固件和 CANN 版本符合要求;

• 检查 memlock 限制;

• P2P 场景可尝试开启 use_host_staging: True,用有限的 os_staging_bytes 替代完整 CPU cache 注册;

• 若完整缓存注册稳定,关闭 HostStaging 通常可减少一次 CPU 拷贝。

7.5 短 prompt 在 1P1D 中未发生传输 ​

检查 Prefill 是否同时设置:

yaml
save_unfull_chunk: True

以及 connector 配置是否包含:

json
{"discard_partial_chunks": false}

两者用于保留不足完整 chunk 的尾部缓存。

7.6 P2P delayed pull 未生效 ​

确保:

yaml
p2p_pull_mode: True
p2p_delay_pull: True
p2p_use_npu: True

若启用 HostStaging,还必须使用 transfer_channel: "hccl"。HIXL 当前不支持 HostStaging。