Sparse KV Offload 部署指南
1. 概述
在昇腾 A3 上部署 PD 分离 推理,并在 Decode 启用 Sparse KV Offload(可选 小包聚合)。适用 DeepSeek-V3.2 等带 index_topk 的 DSA / SFA 模型。
- Sparse KV Offload:完整 Decode KV 放 Host DDR(MemFabric SHARED),NPU 仅保留 Indexer 与 top-K 热缓冲,miss 时 H2D onload。Prefill 可用 Layerwise(memcache)省 HBM;P→D 经
SfaRemoteD2HConnector直写 Decode Host pool。 - 小包聚合(可选):eager 路径下 TP0 聚包后一次 H2D,再 broadcast/scatter,降低离散小包 DMA 开销。代码在私仓分支,未合入官方 v0.26.0rc1;常规部署用官方
releases/v0.26.0rc。私仓:https://github.com/zd1204/vllm-ascend/tree/group_aggregation_cpu - 组件:vLLM / vLLM-Ascend、MemFabric、MemCache(仅 P)、PD Proxy。
2. 环境准备
| KEY | VALUE |
|---|---|
| 服务器 | 建议 2 台昇腾 A3(一台 P、一台 D) |
| 操作系统 | openEuler(与镜像匹配) |
| 容器镜像 | quay.io/ascend/vllm-ascend:v0.26.0rc1-a3-openeuler |
| vLLM / vLLM-Ascend | releases/v0.26.0 / 官方 releases/v0.26.0rc(小包聚合可选私仓 group_aggregation_cpu) |
| MemFabric / MemCache | release/1.2(MemCache 仅 P) |
| 模型示例 | /data/models/DeepSeek-V3.2-W8A8 |
P/D 需互通。下文示例 P=10.0.1.10、D=10.0.1.11。nic_name / local_ip 在容器外用 ip addr 查看后填入。
3. 部署流程
3.1 启动容器(P、D)
--network=host;-v /nvme1n1:/data 可按需改;--device /dev/davinci* 按实际 NPU 增减。
docker run \
--ipc=host \
-u 0 \
--name vllm-offloading-test \
--privileged \
--network=host \
--device /dev/davinci0 \
--device /dev/davinci1 \
--device /dev/davinci2 \
--device /dev/davinci3 \
--device /dev/davinci4 \
--device /dev/davinci5 \
--device /dev/davinci6 \
--device /dev/davinci7 \
--device /dev/davinci8 \
--device /dev/davinci9 \
--device /dev/davinci10 \
--device /dev/davinci11 \
--device /dev/davinci12 \
--device /dev/davinci13 \
--device /dev/davinci14 \
--device /dev/davinci15 \
--device=/dev/davinci_manager \
--device=/dev/devmm_svm \
--device=/dev/hisi_hdc \
-v /usr/local/Ascend/driver:/usr/local/Ascend/driver \
-v /usr/local/Ascend/add-ons/:/usr/local/Ascend/add-ons/ \
-v /usr/local/sbin/npu-smi:/usr/local/sbin/npu-smi \
-v /usr/local/sbin/:/usr/local/sbin/ \
-v /var/log/npu/conf/slog/slog.conf:/var/log/npu/conf/slog/slog.conf \
-v /var/log/npu/slog/:/var/log/npu/slog \
-v /var/log/npu/profiling/:/var/log/npu/profiling \
-v /var/log/npu/dump/:/var/log/npu/dump \
-v /usr/local/Ascend/driver/tools/hccn_tool:/usr/local/Ascend/driver/tools/hccn_tool \
-v /nvme1n1:/data \
-e GIT_SSL_NO_VERIFY=true \
-dit \
quay.io/ascend/vllm-ascend:v0.26.0rc1-a3-openeuler \
bash3.2 编译安装依赖(P、D;MemCache 仅 P)
pip uninstall -y vllm
pip uninstall -y vllm-ascend
# vLLM
git clone https://gh-proxy.org/https://github.com/vllm-project/vllm.git -b releases/v0.26.0
pip install setuptools_rust
cd vllm/
VLLM_TARGET_DEVICE=empty pip install -v -e . --no-build-isolation -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple
pip install matplotlib msguard openpyxl tzdata -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple
cd ..
# vLLM-Ascend(官方;不含小包聚合,见第 4 节)
git clone https://gh-proxy.org/https://github.com/vllm-project/vllm-ascend.git -b releases/v0.26.0rc
cd vllm-ascend/
pip install -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple \
--trusted-host mirrors.huaweicloud.com \
--extra-index-url https://mirrors.huaweicloud.com/ascend/repos/pypi \
-v -e .
cd ..
# MemFabric
pip uninstall -y memfabric_hybrid
git clone https://gitcode.com/Ascend/memfabric_hybrid.git -b release/1.2
cd memfabric_hybrid/
bash script/build_and_pack_run.sh
bash output/memfabric_hybrid-1.2.1_linux_aarch64.run
cd ..
# MemCache(仅 P)
pip uninstall -y memcache_hybrid
git clone https://gitcode.com/Ascend/memcache.git -b release/1.2
cd memcache/
git submodule init
git submodule update
cd 3rdparty/
rm -rf memfabric_hybrid
git clone https://gitcode.com/Ascend/memfabric_hybrid.git -b release/1.2
cd ..
bash script/build_and_pack_run.sh
bash output/memcache_hybrid-1.2.0_linux_aarch64.run
cd ..P 节点编辑 /usr/local/memcache_hybrid/latest/config/mmc-local.conf:
| 配置项 | 建议值 |
|---|---|
ock.mmc.local_service.protocol | host_shm |
ock.mmc.local_service.dram.size | 10G(按内存调整) |
3.3 环境变量(P、D)
追加到 ~/.bashrc(改 nic_name / local_ip;MEMFABRIC_HYBRID_EXTEND_LIB_PATH 版本号与安装包一致),然后 source ~/.bashrc:
nic_name="xxxxxx" # 容器外 ip addr
local_ip=x.x.x.x
export HCCL_IF_IP=$local_ip
export HCCL_IF_BASE_PORT=50000
export GLOO_SOCKET_IFNAME=$nic_name
export TP_SOCKET_IFNAME=$nic_name
export HCCL_SOCKET_IFNAME=$nic_name
export HCCL_BUFFSIZE=400
export HCCL_OP_EXPANSION_MODE="AIV"
export VLLM_EXECUTE_MODEL_TIMEOUT_SECONDS=3000
export OMP_PROC_BIND=false
export OMP_NUM_THREADS=1
export VLLM_USE_V1=1
export VLLM_WORKER_MULTIPROC_METHOD=spawn
source /usr/local/memfabric_hybrid/set_env.sh
export MMC_LOCAL_CONFIG_PATH=/usr/local/memcache_hybrid/latest/config/mmc-local.conf
export MEMFABRIC_HYBRID_EXTEND_LIB_PATH=/usr/local/memfabric_hybrid/1.2.1/aarch64-linux/lib64
export PYTHONHASHSEED=03.4 启动 MemCache Meta(仅 P)
mkdir -p /workdir
cd /workdir创建 start_meta.sh:
#!/bin/bash
source /usr/local/memcache_hybrid/set_env.sh
source /usr/local/memfabric_hybrid/set_env.sh
export MMC_META_CONFIG_PATH=/usr/local/memcache_hybrid/latest/config/mmc-meta.conf
python -c "from memcache_hybrid import MetaService; MetaService.main()"chmod +x ./start_meta.sh
nohup ./start_meta.sh 2>&1 &3.5 启动 Prefill(P)
--tensor-parallel-size 与 NPU 数一致;端口需与代理一致。SfaRemoteD2HConnector 写 Decode Host pool;AscendStoreConnector + use_layerwise 为 Prefill Layerwise。
vllm serve /data/models/DeepSeek-V3.2-W8A8 \
--host 0.0.0.0 \
--port 29180 \
--tensor-parallel-size 16 \
--served-model-name deepseek-v3.2 \
--max-num-seqs 4 \
--block-size 128 \
--max-model-len 132096 \
--trust-remote-code \
--gpu-memory-utilization 0.95 \
--quantization ascend \
--enable-chunked-prefill \
--max-num-batched-tokens 1024 \
--enable-prefix-caching \
--enable-expert-parallel \
--speculative-config '{"method": "mtp", "num_speculative_tokens": 3}' \
--kv-transfer-config '{
"kv_connector": "MultiConnector",
"kv_role": "kv_producer",
"kv_connector_extra_config": {
"connectors": [
{
"kv_connector": "SfaRemoteD2HConnector",
"kv_role": "kv_producer",
"kv_connector_extra_config": {
"transfer_backend": "memfabric"
}
},
{
"kv_connector": "AscendStoreConnector",
"kv_role": "kv_producer",
"kv_connector_extra_config": {
"backend": "memcache",
"use_layerwise": true,
"layerwise_num_shared_buffers": 3,
"layerwise_independent_layers": [0]
}
}
]
}
}' \
--safetensors-load-strategy 'prefetch' \
--additional-config '{
"enable_mlapo": false
}'3.6 启动 Decode(D,含 Sparse KV Offload)
kv_role: kv_consumer;sparse_kv_offload_config.enabled: truetopk_buffer_size≥index_topk且能被block_size整除(实践可取2 * index_topk)dram_size_per_dp_GB须能放下该 DP 完整 KV;配置非法会导致启动/运行失败
vllm serve /data/models/DeepSeek-V3.2-W8A8 \
--host 0.0.0.0 \
--port 29181 \
--tensor-parallel-size 16 \
--served-model-name deepseek-v3.2 \
--max-num-seqs 4 \
--block-size 128 \
--max-model-len 132096 \
--trust-remote-code \
--gpu-memory-utilization 0.95 \
--quantization ascend \
--enable-chunked-prefill \
--max-num-batched-tokens 120 \
--no-enable-prefix-caching \
--enable-expert-parallel \
--speculative-config '{"method": "mtp", "num_speculative_tokens": 3}' \
--compilation-config '{"cudagraph_mode":"FULL_DECODE_ONLY"}' \
--kv-transfer-config '{
"kv_connector": "SfaRemoteD2HConnector",
"kv_role": "kv_consumer",
"kv_port": 20050,
"kv_connector_extra_config": {
"transfer_backend": "memfabric",
"use_layerwise": true
}
}' \
--safetensors-load-strategy 'prefetch' \
--additional-config '{
"enable_mlapo": false,
"sparse_kv_offload_config": {
"enabled": true,
"topk_buffer_size": 4096,
"dram_size_per_dp_GB": 512
}
}'3.7 启动 PD 代理(P 容器)与压测
客户端访问 http://<P_IP>:21600。长序列(如 >64K / 128K)更易观察 Offload 收益;关注 tpot 与吞吐。
cd /workspace/vllm-ascend/examples/disaggregated_prefill_v1
# 若源码在其它路径,请改为实际 vllm-ascend 目录下的 examples 路径
python load_balance_proxy_layerwise_server_example.py \
--host 10.0.1.10 \
--port 21600 \
--prefiller-hosts 10.0.1.10 \
--prefiller-ports 29180 \
--decoder-hosts 10.0.1.11 \
--decoder-ports 29181vllm bench serve \
--backend openai \
--base-url http://10.0.1.10:21600 \
--endpoint /v1/completions \
--model deepseek-v3.2 \
--tokenizer /data/models/DeepSeek-V3.2-W8A8 \
--trust-remote-code \
--skip-chat-template \
--dataset-name custom \
--dataset-path long_prompts99/prompts_128k_8_prefix_cache99.jsonl \
--percentile-metrics ttft,tpot \
--metric-percentiles 0,50,90,99,100 \
--custom-output-len 1024 \
--num-prompts 1 \
--max-concurrency 1 \
--ignore-eos \
--temperature 03.8 约束
- 仅支持带
index_topk的稀疏注意力;不支持 compress ratio、CP、PP、Model Runner V2(以当前实现为准)。 - 生产路径为 PD Decode(
kv_consumer)。 - MemCache Meta /
mmc-local.conf仅 P;D 侧重 MemFabric + Sparse Offload。
4. 小包聚合(可选)
叠加在 Decode Sparse Offload onload 上。官方 v0.26.0rc1 不含此能力,需私仓:https://github.com/zd1204/vllm-ascend/tree/group_aggregation_cpu
pip uninstall -y vllm-ascend
# 国内可加 https://gh-proxy.org/ 前缀
git clone https://github.com/zd1204/vllm-ascend.git -b group_aggregation_cpu
cd vllm-ascend/
pip install -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple \
--trusted-host mirrors.huaweicloud.com \
--extra-index-url https://mirrors.huaweicloud.com/ascend/repos/pypi \
-v -e .
cd ..Decode 启动前:
export VLLM_ASCEND_ENABLE_CPU_GATHER_H2D=1
export VLLM_ASCEND_CPU_GATHER_THREADS=4
export VLLM_ASCEND_CPU_GATHER_BUFFER_BYTES=8388608关闭:
export VLLM_ASCEND_ENABLE_CPU_GATHER_H2D=0然后按 3.6 启动 Decode(须已开 Offload),再按 3.7 代理与压测。对比开关时仅改环境变量并重启 Decode。
注意:仅 Decode;多 TP 时仅 TP0 pack+H2D 再 broadcast;pack 失败 fallback 离散 sparse_copy;eager-only(ACL Graph 回退离散路径);官方包仅设环境变量无效。VLLM_ASCEND_CPU_GATHER_THREADS 建议 4 或 8;VLLM_ASCEND_CPU_GATHER_BUFFER_BYTES 为 packed 下限(默认 8 MiB)。
5. Mooncake 基线(可选)
不用 MemFabric Sparse Offload 时,可用 Mooncake Layerwise 作基线(P/D 均无 sparse_kv_offload_config)。其余参数同 3.5 / 3.6,仅替换 --kv-transfer-config;代理与 bench 同 3.7。
Prefill:
--kv-transfer-config '{
"kv_connector": "MooncakeLayerwiseConnector",
"kv_role": "kv_producer",
"kv_port": 25000,
"kv_connector_extra_config": {
"prefill": {"dp_size": 1, "tp_size": 16},
"decode": {"dp_size": 1, "tp_size": 16}
}
}'Decode:
--kv-transfer-config '{
"kv_connector": "MooncakeLayerwiseConnector",
"kv_role": "kv_consumer",
"kv_port": 26000,
"kv_connector_extra_config": {
"prefill": {"dp_size": 1, "tp_size": 16},
"decode": {"dp_size": 1, "tp_size": 16}
}
}'