UCM Store 部署指南¶
为什么要使用 UCM¶
统一缓存管理器(UCM)提供了一个外部 KV 缓存存储层,专为 vLLM/vLLM-Ascend 中的前缀缓存场景而设计。与 KV Pooling 仅通过聚合设备内存来扩展前缀缓存容量、因此仍受限于 HBM/DRAM 大小且缺乏持久性不同,UCM 将计算与存储解耦,并采用分层设计。每个节点使用本地 DRAM 作为快速缓存,而共享后端(如 NFS、3FS 或企业级存储)则作为持久化 KV 存储。
使用 UCM 的关键优势:
-
打破设备内存容量限制:传统前缀缓存受限于 HBM/DRAM 大小。UCM 通过将 KV 缓存卸载到外部存储来消除这一上限,使缓存容量能够随存储系统而非计算资源进行扩展。
-
持久化且可靠的 KV 缓存:UCM 提供持久的 KV 缓存存储,确保缓存的 prefix 块能够在服务重启、实例故障或调度迁移后仍然存在。这对于生产级推理系统至关重要。
-
多场景加速:UCM 不仅支持前缀缓存,还提供免训练的稀疏注意力方法(如 GSA、CacheBlend),用于处理超长序列推理任务。此外,UCM 还提供基于存算分离架构的 PD 分离解决方案,支持异构计算资源的灵活管理。
-
显著的性能提升:与 vLLM 集成后,UCM 在多轮对话和长上下文推理等各类场景中实现 3-10 倍的推理延迟降低。基准测试显示,在前缀缓存场景中 TTFT 最高可提升 8 倍。
UCM 工作原理¶
架构¶
UCM 采用集中式架构进行 KV 缓存管理,构建三层缓存层次结构:
这一三层设计能够实现:
- HBM(第一层):为活跃推理计算提供最快的访问速度
- DRAM(第二层):为频繁访问的 KV 块提供高速本地缓存
- 存储后端(第三层):持久化存储层,包括本地 SSD、NFS 挂载存储或 3FS 等专用系统,支持无限容量扩展
UCM 选择集中式方案(类似于 DeepSeek 的 3FS)而非去中心化设计,原因如下:
- 简单性:避免了去中心化架构中所需的复杂亲和性调度
- 解耦:保持推理实例独立,无需向调度器上报 KV 缓存状态
- 无数据孤岛:集中式存储可避免跨隔离实例的冗余 KV 缓存累积
- 更好的兼容性:与 PD 分离及大规模部署具有更优的兼容性
功能特性¶
UCM 目前提供以下功能:
| 功能 | 描述 |
|---|---|
| Prefix Cache | 持久化 KV 缓存存储,支持 NFS Store、3FS Store 和 Pipeline Store |
| Sparse Attention | 免训练的稀疏注意力方法,包括 GSA(基于图的稀疏注意力)和 CacheBlend,用于长上下文加速 |
| PD Disaggregation | Prefill-Decode 分离,支持多种模式:P2P、集中式 PD、NPGD 和 xPYD |
| ReRoPE | 支持旋转位置编码扩展 |
支持的平台:
- CUDA(NVIDIA H100、H20、L40、L20)
- CANN(Atlas A2 推理产品、Atlas A3 推理产品)
- MUSA(Mthreads S5000)
- MACA(MetaX C500)
支持的框架:
- vLLM(main 分支)
- vLLM-Ascend(main 分支)
- SGLang(main 分支)
注意:完整的支持矩阵及最新信息,请参阅 UCM Support Matrix。
部署指南¶
前提条件¶
- 操作系统:Linux
- 配备 Ascend NPU 的硬件,通常为 Atlas 800 A2 系列
- vLLM:main 分支
- vLLM Ascend:main 分支
UCM 安装¶
PD 分离场景¶
UCM 支持两种类型的 PD 分离架构:
| 类型 | KV 传输方式 | 特点 |
|---|---|---|
| Centralized PD | 通过统一存储后端(NFS/3FS)传输 | 架构简单、完全解耦、实例无状态 |
| Distributed PD(P2P) | 通过 Mooncake + UCM prefix cache 直接传输 | 延迟更低,适用于同构 P/D 节点 |
集中式 PD 分离¶
在集中式 PD 分离架构中,KV 缓存通过统一存储池进行传输。Prefill 节点将 KV 缓存卸载到存储后端,Decode 节点以高前缀缓存命中率进行读取。这种方式实现了最高程度的解耦,并简化了调度逻辑。
重要:对于跨节点部署,所有 Prefill 和 Decode 节点必须能够访问共享存储后端(例如 NFS 挂载目录或 3FS)。在继续之前,请确保所有节点都能访问该存储路径。
示例:2P2D 部署
假设节点 192.168.10.1 上有 2 个 Prefill 实例(端口 7800、7801),节点 192.168.10.2 上有 2 个 Decode 实例(端口 7802、7803),共享 NFS 存储位于 /mnt/test1。
步骤 1:准备 UCM 配置文件
使用 PipelineStore 创建配置文件(例如 ucm_config_example.yaml):
ucm_connectors:
- ucm_connector_name: "UcmPipelineStore"
ucm_connector_config:
store_pipeline: "Cache|Posix"
storage_backends: "/mnt/test1"
cache_buffer_capacity_gb: 64
enable_event_sync: true
use_layerwise: false
关键配置参数:
- storage_backends:所有节点均可访问的共享存储目录(例如 NFS 挂载路径或 3FS)。对于跨节点 PD 分离,该路径必须是共享存储路径。
注意:PipelineStore 是 UCM 推荐的连接器。它将 Cache Store(设备 ↔ 主机)与 Posix Store(主机 ↔ 存储后端)链接起来,以获得最佳传输性能。更多配置选项请参阅 UCM PipelineStore 文档。
步骤 2:运行 Prefill 服务器
export PYTHONHASHSEED=123456
export ASCEND_RT_VISIBLE_DEVICES=0,1,2,3
vllm serve /models/QwQ-32B \
--host 0.0.0.0 \
--port 7800 \
--gpu-memory-utilization 0.92 \
--data-parallel-size 1 \
--tensor-parallel-size 4 \
--seed 1024 \
--max-model-len 17000 \
--max-num-batched-tokens 8000 \
--max-num-seqs 20 \
--trust-remote-code \
--enforce-eager \
--kv-transfer-config \
'{
"kv_connector": "UCMConnector",
"kv_role": "kv_both",
"kv_connector_extra_config": {"UCM_CONFIG_FILE": "/path/to/ucm_config_example.yaml"}
}'
要在同一节点上启动第二个 Prefill 实例,请相应修改 --port(例如端口 7801)和 ASCEND_RT_VISIBLE_DEVICES。
步骤 3:运行 Decode 服务器
export PYTHONHASHSEED=123456
export ASCEND_RT_VISIBLE_DEVICES=0,1,2,3
vllm serve /models/QwQ-32B \
--host 0.0.0.0 \
--port 7802 \
--gpu-memory-utilization 0.92 \
--data-parallel-size 1 \
--tensor-parallel-size 4 \
--seed 1024 \
--max-model-len 17000 \
--max-num-batched-tokens 8000 \
--max-num-seqs 20 \
--trust-remote-code \
--compilation-config '{"cudagraph_mode":"FULL_DECODE_ONLY"}' \
--kv-transfer-config \
'{
"kv_connector": "UCMConnector",
"kv_role": "kv_both",
"kv_connector_extra_config": {"UCM_CONFIG_FILE": "/path/to/ucm_config_example.yaml"}
}'
要在同一节点上启动第二个 Decode 实例,请相应修改 --port(例如端口 7803)和 ASCEND_RT_VISIBLE_DEVICES。
步骤 4:运行负载均衡服务
python /vllm-workspace/vllm-ascend/examples/disaggregated_prefill_v1/load_balance_proxy_server_example.py \
--port 7805 \
--host 0.0.0.0 \
--prefiller-hosts 192.168.10.1 192.168.10.1 \
--prefiller-ports 7800 7801 \
--decoder-hosts 192.168.10.2 192.168.10.2 \
--decoder-ports 7802 7803
步骤 5:性能测试
vllm bench serve \
--backend vllm \
--model /models/QwQ-32B \
--host 192.168.10.1 \
--port 7805 \
--seed 123456 \
--dataset-name random \
--num-prompts 10 \
--random-input-len 8000 \
--random-output-len 1000 \
--request-rate inf \
--ignore-eos
分布式 PD 分离(P2P)¶
在 P2P 分布式 PD 分离中,Mooncake 通过高速网络处理从 Prefill 节点到 Decode 节点的直接 KV 缓存传输,而 UCM 在 Prefill 节点上提供前缀缓存以实现 KV 缓存复用。该模式适用于 P/D 节点同构且延迟要求较低的场景。
注意:从 vLLM-Ascend 0.11.0 开始,官方镜像中已预装 Mooncake。安装详情请参阅 kvcache-ai/Mooncake。
示例:2P2D 配置
假设节点 192.168.10.1 上有 2 个 Prefill 实例(端口 9000、9001),节点 192.168.10.2 上有 2 个 Decode 实例(端口 9000、9001)。
步骤 1:运行 Mooncake Master 服务
在任意节点(例如 192.168.10.1)上运行 Mooncake master:
export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
mooncake_master --port 50088 \
--eviction_high_watermark_ratio 0.9 \
--eviction_ratio 0.1 \
--default_kv_lease_ttl 11000
在每个节点上准备 mooncake.json:
{
"metadata_server": "P2PHANDSHAKE",
"protocol": "ascend",
"device_name": "",
"master_server_address": "192.168.10.1:50088",
"global_segment_size": "1GB"
}
同时为 Prefill 节点准备用于前缀缓存的 UCM 配置文件(ucm_config_example.yaml):
ucm_connectors:
- ucm_connector_name: "UcmPipelineStore"
ucm_connector_config:
store_pipeline: "Cache|Posix"
storage_backends: "/mnt/test1"
cache_buffer_capacity_gb: 64
enable_event_sync: true
use_layerwise: true
注意:更多配置选项请参阅 UCM PipelineStore 文档。
步骤 2:运行 Prefill 服务
export LD_LIBRARY_PATH=/usr/local/lib:/usr/local/Ascend/ascend-toolkit/latest/python/site-packages:$LD_LIBRARY_PATH
export PYTHONHASHSEED=0
export PYTHONPATH=$PYTHONPATH:/vllm-workspace/vllm
export MOONCAKE_CONFIG_PATH="./mooncake.json"
export ASCEND_RT_VISIBLE_DEVICES=0,1,2,3
vllm serve /models/QwQ-32B \
--host 0.0.0.0 \
--port 9000 \
--gpu-memory-utilization 0.92 \
--data-parallel-size 1 \
--tensor-parallel-size 4 \
--seed 1024 \
--max-model-len 17000 \
--max-num-batched-tokens 8000 \
--max-num-seqs 20 \
--trust-remote-code \
--enforce-eager \
--kv-transfer-config \
'{
"kv_connector": "MultiConnector",
"kv_role": "kv_producer",
"kv_connector_extra_config": {
"connectors": [
{
"kv_connector": "MooncakeConnectorV1",
"kv_role": "kv_producer",
"kv_port": 20001,
"kv_connector_extra_config": {
"prefill": {"dp_size": 1, "tp_size": 4},
"decode": {"dp_size": 1, "tp_size": 4}
}
},
{
"kv_connector": "UCMConnector",
"kv_role": "kv_both",
"kv_connector_extra_config": {"UCM_CONFIG_FILE": "/vllm-workspace/unified-cache-management/examples/ucm_config_example.yaml"}
}
]
}
}'
要在同一节点上启动多个 Prefill 实例,请为每个实例修改 --port、kv_port 和 ASCEND_RT_VISIBLE_DEVICES(例如,第二个实例使用端口 9001 和 kv_port 20002)。
步骤 3:运行解码服务
export LD_LIBRARY_PATH=/usr/local/lib:/usr/local/Ascend/ascend-toolkit/latest/python/site-packages:$LD_LIBRARY_PATH
export PYTHONHASHSEED=0
export PYTHONPATH=$PYTHONPATH:/vllm-workspace/vllm
export MOONCAKE_CONFIG_PATH="./mooncake.json"
export ASCEND_RT_VISIBLE_DEVICES=0,1,2,3
vllm serve /models/QwQ-32B \
--host 0.0.0.0 \
--port 9000 \
--data-parallel-size 1 \
--tensor-parallel-size 4 \
--seed 1024 \
--max-model-len 17000 \
--max-num-batched-tokens 8000 \
--trust-remote-code \
--max-num-seqs 4 \
--gpu-memory-utilization 0.92 \
--compilation-config '{"cudagraph_mode":"FULL_DECODE_ONLY"}' \
--kv-transfer-config \
'{
"kv_connector": "MooncakeConnectorV1",
"kv_role": "kv_consumer",
"kv_port": 20001,
"kv_connector_extra_config": {
"prefill": {"dp_size": 1, "tp_size": 4},
"decode": {"dp_size": 1, "tp_size": 4}
}
}'
要在同一节点上启动多个解码实例,请为每个实例修改 --port、kv_port 和 ASCEND_RT_VISIBLE_DEVICES(例如,第二个实例使用端口 9001 和 kv_port 20002)。
步骤 4:运行负载均衡服务
python /vllm-workspace/vllm-ascend/examples/disaggregated_prefill_v1/load_balance_proxy_server_example.py \
--port 7850 \
--host 0.0.0.0 \
--prefiller-hosts 192.168.10.1 192.168.10.1 \
--prefiller-ports 9000 9001 \
--decoder-hosts 192.168.10.2 192.168.10.2 \
--decoder-ports 9000 9001
步骤 5:性能测试
vllm bench serve \
--backend vllm \
--model /models/QwQ-32B \
--host 192.168.10.1 \
--port 7850 \
--seed 123456 \
--dataset-name random \
--num-prompts 10 \
--random-input-len 8000 \
--random-output-len 1000 \
--request-rate inf \
--ignore-eos
PD 混合推理¶
PD 混合推理(PD-Mixed Inference)指的是标准 vLLM 服务模式,其中不同请求的预填充(Prefill)和解码(Decode)阶段在同一实例内并发处理。与将预填充和解码物理分离到专用实例的 PD 分离(PD Disaggregation)不同,PD 混合模式在统一调度器中处理两个阶段,允许交错执行:当一个请求处于解码阶段时,另一个请求可以同时进行预填充。
UCM 通过提供持久化 KV 缓存存储来增强 PD 混合模式,可实现:
- 跨请求共享前缀的前缀缓存复用
- 服务重启后 KV 缓存的持久化
- 将 KV 缓存卸载到外部存储以降低 GPU 内存压力
步骤 1:准备 UCM 配置文件
创建包含 PipelineStore 的配置文件(例如 ucm_config_example.yaml):
ucm_connectors:
- ucm_connector_name: "UcmPipelineStore"
ucm_connector_config:
store_pipeline: "Cache|Posix"
storage_backends: "/mnt/test1"
cache_buffer_capacity_gb: 64
enable_event_sync: true
use_layerwise: true
关键配置参数:
- storage_backends:KV 缓存存储目录。可以是本地 SSD 或 NFS 挂载路径。
注意:更多配置选项,请参阅 UCM PipelineStore 文档。
步骤 2:运行 PD 混合服务
export ASCEND_RT_VISIBLE_DEVICES=0,1,2,3,4,5,6,7
vllm serve /models/QwQ-32B \
--host 0.0.0.0 \
--port 7800 \
--gpu-memory-utilization 0.92 \
--data-parallel-size 2 \
--tensor-parallel-size 4 \
--seed 1024 \
--max-model-len 17000 \
--max-num-batched-tokens 8000 \
--max-num-seqs 20 \
--trust-remote-code \
--enforce-eager \
--block-size 128 \
--kv-transfer-config \
'{
"kv_connector": "UCMConnector",
"kv_role": "kv_both",
"kv_connector_extra_config": {"UCM_CONFIG_FILE": "/path/to/ucm_config_example.yaml"}
}'
步骤 3:性能测试
运行两次基准测试以观察前缀缓存效果:
# First run - no cache hit
vllm bench serve \
--backend vllm \
--model /models/QwQ-32B \
--host localhost \
--port 7800 \
--seed 123456 \
--dataset-name random \
--num-prompts 10 \
--random-input-len 8000 \
--random-output-len 1000 \
--request-rate inf \
--ignore-eos
# Second run - observe cache hit improvement
vllm bench serve \
--backend vllm \
--model /models/QwQ-32B \
--host localhost \
--port 7800 \
--seed 123456 \
--dataset-name random \
--num-prompts 10 \
--random-input-len 8000 \
--random-output-len 1000 \
--request-rate inf \
--ignore-eos
第二次运行后,由于 UCM 前缀缓存命中,应观察到 TTFT 显著降低。请查看 vLLM 日志中的缓存命中信息:
示例:大规模专家并行下的 PD 分离¶
本节演示了在大规模专家并行(Expert Parallelism)下,针对 MoE 模型的 PD 分离部署。MoE 模型需要启用数据并行,以将专家权重分布到多个节点。
部署配置:
- 预填充实例:4 个节点(192.168.10.1-4),DP4TP8(4 个 DP 进程,每个使用 TP8)
- 解码实例:4 个节点(192.168.10.5-8),DP8TP4(8 个 DP 进程,每个使用 TP4)
- 总计:8 台 Atlas 800T A2 服务器,每台配备 8 张 Ascend 910B3 NPU 卡
- 存储:8 台服务器通过 CE8875 交换机连接到 AI 存储设备 A800
注意:关于外部负载均衡的数据并行,请参阅 vLLM 官方文档:外部负载均衡的数据并行部署。
部署步骤¶
步骤 1:运行 Mooncake 主服务
在任意节点(例如 192.168.10.1)上运行 Mooncake 主服务:
export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
mooncake_master --port 50088 \
--eviction_high_watermark_ratio 0.9 \
--eviction_ratio 0.1 \
--default_kv_lease_ttl 11000
在所有 8 个节点上准备 mooncake.json:
{
"metadata_server": "P2PHANDSHAKE",
"protocol": "ascend",
"device_name": "",
"master_server_address": "192.168.10.1:50088",
"global_segment_size": "1GB"
}
步骤 2:运行 Prefill 服务(DP4TP8)
首先,在 Prefill 节点(192.168.10.1-4)上为前缀缓存准备一个 UCM 配置文件(ucm_config_example.yaml):
ucm_connectors:
- ucm_connector_name: "UcmPipelineStore"
ucm_connector_config:
store_pipeline: "Cache|Posix"
storage_backends: "/mnt/test1"
cache_buffer_capacity_gb: 64
enable_event_sync: true
use_layerwise: true
关键配置参数:
- storage_backends:所有节点均可访问的共享存储目录(例如 NFS 挂载路径或 3FS)。
注意:更多配置选项请参阅 UCM PipelineStore 文档。
在 Prefill 节点(192.168.10.1-4)上准备 prefill.sh:
#!/bin/sh
export LD_LIBRARY_PATH=/usr/local/lib:/usr/local/Ascend/ascend-toolkit/latest/python/site-packages:$LD_LIBRARY_PATH
export PYTHONHASHSEED=0
export PYTHONPATH=$PYTHONPATH:/vllm-workspace/vllm
export MOONCAKE_CONFIG_PATH="./mooncake.json"
device_list=$1
local_ip=$2
nic_name=$3
server_port=$4
tp_size=$5
dp_size=$6
dp_rank=$7
dp_address=$8
dp_rpc_port=$9
mooncake_port=${10}
export HCCL_IF_IP=$local_ip
export GLOO_SOCKET_IFNAME=$nic_name
export TP_SOCKET_IFNAME=$nic_name
export HCCL_SOCKET_IFNAME=$nic_name
export OMP_PROC_BIND=false
export OMP_NUM_THREADS=10
export HCCL_BUFFSIZE=256
export ASCEND_RT_VISIBLE_DEVICES=$device_list
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export TASK_QUEUE_ENABLE=1
export VLLM_USE_MODELSCOPE="True"
vllm serve /models/GLM-5.1-w4a8 \
--host 0.0.0.0 \
--port $server_port \
--data-parallel-size $dp_size \
--data-parallel-address $dp_address \
--data-parallel-rpc-port $dp_rpc_port \
--data-parallel-rank $dp_rank \
--tensor-parallel-size $tp_size \
--enable-expert-parallel \
--seed 1024 \
--max-model-len 17000 \
--max-num-batched-tokens 8000 \
--trust-remote-code \
--max-num-seqs 4 \
--gpu-memory-utilization 0.92 \
--quantization ascend \
--enforce-eager \
--additional-config '{"enable_weight_nz_layout":true,"enable_prefill_optimizations":true}' \
--kv-transfer-config \
'{
"kv_connector": "MultiConnector",
"kv_role": "kv_producer",
"kv_connector_extra_config": {
"connectors": [
{
"kv_connector": "MooncakeConnectorV1",
"kv_role": "kv_producer",
"kv_port": '$mooncake_port',
"kv_connector_extra_config": {
"prefill": {"dp_size": '$dp_size', "tp_size": '$tp_size'},
"decode": {"dp_size": 8, "tp_size": 4}
}
},
{
"kv_connector": "UCMConnector",
"kv_role": "kv_both",
"kv_connector_extra_config": {"UCM_CONFIG_FILE": "/path/to/ucm_config_example.yaml"}
}
]
}
}' 2>&1 | tee "prefiller_dp_$dp_rank.log"
为 Prefill 节点准备 run_multi_dp.sh:
#!/bin/bash
local_ip="xxxx" # IP of current node (192.168.10.1/2/3/4)
nic_name="xxxx" # Network interface name corresponding to local_ip
tp_size=8
dp_size=4 # Total DP engines for Prefill
dp_size_local=1 # 1 DP process per node (TP8 uses all 8 cards)
dp_rank_start=xxxx # 0 for node1, 1 for node2, 2 for node3, 3 for node4
dp_address="192.168.10.1" # Master node for DP communication
dp_rpc_port=13395
server_port=9000
mooncake_port=20001
template_path="./prefill.sh"
cards_per_node=8
cards_per_process=$((cards_per_node / dp_size_local))
for ((i=0; i<dp_size_local; i++)); do
dp_rank=$((dp_rank_start + i))
server_port=$((server_port + i))
mooncake_port=$((mooncake_port + i * tp_size))
start_card=$((i * cards_per_process))
device_list=$(seq -s, $start_card $((start_card + cards_per_process - 1)))
bash $template_path $device_list $local_ip $nic_name $server_port $tp_size $dp_size $dp_rank $dp_address $dp_rpc_port $mooncake_port &
done
wait
在每个 Prefill 节点(192.168.10.1-4)上执行 run_multi_dp.sh,并配置相应的 local_ip 和 dp_rank_start:
- 192.168.10.1:
dp_rank_start=0 - 192.168.10.2:
dp_rank_start=1 - 192.168.10.3:
dp_rank_start=2 - 192.168.10.4:
dp_rank_start=3
步骤 3:运行 Decode 服务(DP8TP4)
在 Decode 节点(192.168.10.5-8)上准备 decode.sh:
#!/bin/sh
export LD_LIBRARY_PATH=/usr/local/lib:/usr/local/Ascend/ascend-toolkit/latest/python/site-packages:$LD_LIBRARY_PATH
export PYTHONHASHSEED=0
export PYTHONPATH=$PYTHONPATH:/vllm-workspace/vllm
export MOONCAKE_CONFIG_PATH="./mooncake.json"
device_list=$1
local_ip=$2
nic_name=$3
server_port=$4
tp_size=$5
dp_size=$6
dp_rank=$7
dp_address=$8
dp_rpc_port=$9
mooncake_port=${10}
export HCCL_IF_IP=$local_ip
export GLOO_SOCKET_IFNAME=$nic_name
export TP_SOCKET_IFNAME=$nic_name
export HCCL_SOCKET_IFNAME=$nic_name
export OMP_PROC_BIND=false
export OMP_NUM_THREADS=10
export HCCL_BUFFSIZE=256
export ASCEND_RT_VISIBLE_DEVICES=$device_list
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export TASK_QUEUE_ENABLE=1
export VLLM_USE_MODELSCOPE="True"
vllm serve /models/GLM-5.1-w4a8 \
--host 0.0.0.0 \
--port $server_port \
--data-parallel-size $dp_size \
--data-parallel-address $dp_address \
--data-parallel-rpc-port $dp_rpc_port \
--data-parallel-rank $dp_rank \
--tensor-parallel-size $tp_size \
--enable-expert-parallel \
--seed 1024 \
--max-model-len 17000 \
--max-num-batched-tokens 8000 \
--trust-remote-code \
--max-num-seqs 4 \
--gpu-memory-utilization 0.92 \
--quantization ascend \
--compilation-config '{"cudagraph_mode":"FULL_DECODE_ONLY"}' \
--kv-transfer-config \
'{
"kv_connector": "MooncakeConnectorV1",
"kv_role": "kv_consumer",
"kv_port": '$mooncake_port',
"kv_connector_extra_config": {
"prefill": {"dp_size": 4, "tp_size": 8},
"decode": {"dp_size": '$dp_size', "tp_size": '$tp_size'}
}
}' 2>&1 | tee "decoder_dp_$dp_rank.log"
为 Decode 节点准备 run_multi_dp.sh:
#!/bin/bash
local_ip="xxxx" # IP of current node (192.168.10.5/6/7/8)
nic_name="xxxx" # Network interface name corresponding to local_ip
tp_size=4
dp_size=8 # Total DP engines for Decode
dp_size_local=2 # 2 DP processes per node (TP4 uses 4 cards each)
dp_rank_start=xxxx # 0 for node5, 2 for node6, 4 for node7, 6 for node8
dp_address="192.168.10.5" # Master node for DP communication
dp_rpc_port=13395
server_port=9000
mooncake_port=20001
template_path="./decode.sh"
cards_per_node=8
cards_per_process=$((cards_per_node / dp_size_local))
for ((i=0; i<dp_size_local; i++)); do
dp_rank=$((dp_rank_start + i))
server_port=$((server_port + i))
mooncake_port=$((mooncake_port + i * tp_size))
start_card=$((i * cards_per_process))
device_list=$(seq -s, $start_card $((start_card + cards_per_process - 1)))
bash $template_path $device_list $local_ip $nic_name $server_port $tp_size $dp_size $dp_rank $dp_address $dp_rpc_port $mooncake_port &
done
wait
在每个 Decode 节点(192.168.10.5-8)上执行 run_multi_dp.sh,并配置相应的 local_ip 和 dp_rank_start:
- 192.168.10.5:
dp_rank_start=0 - 192.168.10.6:
dp_rank_start=2 - 192.168.10.7:
dp_rank_start=4 - 192.168.10.8:
dp_rank_start=6
第 4 步:运行负载均衡服务
python /vllm-workspace/vllm-ascend/examples/disaggregated_prefill_v1/load_balance_proxy_server_example.py \
--port 7850 \
--host 0.0.0.0 \
--prefiller-hosts 192.168.10.1 192.168.10.2 192.168.10.3 192.168.10.4 \
--prefiller-ports 9000 9000 9000 9000 \
--decoder-hosts 192.168.10.5 192.168.10.5 192.168.10.6 192.168.10.6 192.168.10.7 192.168.10.7 192.168.10.8 192.168.10.8 \
--decoder-ports 9000 9001 9000 9001 9000 9001 9000 9001
基准测试结果¶
以下基准测试展示了 UCM 前缀缓存在大规模专家并行(EP)PD 分离场景中的有效性。
测试配置:
- 总请求数:128
- 请求并发数:128
- 约束条件:总请求数保持在 Prefill 实例可用于 KV 缓存存储的 HBM 容量范围内
KV 缓存预置流程:
每次测试前,必须使用 0.8 的前缀比例预置 KV 缓存:
- 预置阶段:发送 128 个请求,输入长度 =
target_input_length × 0.8,输出长度 = 1,以建立 KV 缓存前缀 - 测试阶段:发送 128 个请求,输入长度为目标输入长度,输出长度 = 1000
以 32k 输入场景为例:
- 预置:128 个请求,包含 25600(32k × 0.8)个输入 token + 1 个输出 token
- 测试:128 个请求,包含 32000 个输入 token + 1000 个输出 token
该流程确保在测量性能之前,前缀部分(输入的 80%)已被缓存,从而模拟真实场景中的前缀复用。
测试命令:
# Step 1: Pre-seed KV cache (25600 = 32000 * 0.8)
vllm bench serve \
--backend vllm \
--model /models/GLM-5.1-w4a8 \
--host 192.168.10.1 \
--port 7850 \
--seed 123456 \
--dataset-name random \
--num-prompts 128 \
--random-input-len 25600 \
--random-output-len 1 \
--request-rate inf \
--ignore-eos
# Step 2: Run performance test
vllm bench serve \
--backend vllm \
--model /models/GLM-5.1-w4a8 \
--host 192.168.10.1 \
--port 7850 \
--seed 123456 \
--dataset-name random \
--num-prompts 128 \
--random-input-len 32000 \
--random-output-len 1000 \
--request-rate inf \
--ignore-eos
测试场景:
| 场景 | 描述 |
|---|---|
| 重计算 | 无 UCM 的基线,禁用 HBM 前缀缓存(完全重计算) |
| HBM PC | 无 UCM,启用 HBM 前缀缓存 |
| UCM PC | 启用 UCM 前缀缓存 |
性能结果:
| 输入长度 | 输出长度 | 重计算 | HBM PC | UCM PC | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| TTFT (ms) | TPOT (ms) | E2EL (ms) | TTFT (ms) | TPOT (ms) | E2EL (ms) | TTFT (ms) | TPOT (ms) | E2EL (ms) | ||
| 32k | 1k | 140730 | 64 | 173820 | 108879 | 65 | 142228 | 51861 | 66 | 85615 |
| 64k | 1k | 181864 | 64 | 214988 | 144444 | 65 | 177561 | 69718 | 66 | 103752 |
| 128k | 1k | 268016 | 65 | 301648 | 267680 | 65 | 301135 | 105083 | 66 | 138946 |
注意:由于数据并行,测试阶段的请求可能不会路由到用于 KV 缓存预置的同一 DP 进程。因此,HBM PC 的实际缓存命中率低于预期的 0.8。UCM 通过将全部 KV 缓存存储在共享外部存储中来解决这一限制,确保无论请求由哪个 DP 进程处理,都能命中缓存数据。这保证了真实缓存命中率等于预置比例 0.8,相比 HBM PC 显著降低了 TTFT。TTFT 的改善有效提升了 Prefill 实例的吞吐量,从而提升了整体系统吞吐量。
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 vl/vllm-ascend