文章目录
Prefill 计算密集、Decode 访存密集——这对天然割裂的阶段,决定了大模型推理并非一锅炖。
把两者解耦(PD 分离)+ 用 vLLM 的 PagedAttention 精准管控 KV Cache,是目前在昇腾场景下把吞吐与成本同时打上去的可靠路径。
我们就用DeepSeek-V3-w8a8为例,完整记录在vLLM-ascend上落地PD 分离的过程与最佳实践,并附常见报错与处理清单,帮助你少走弯路。
1.背景与意义
Prefill:把完整输入编码为隐藏状态并生成初始 KV Cache,计算密集、显存瞬时占用高。
Decode:一次生成一个 token,强依赖 KV Cache 读写,访存/带宽密集、链路易 HostBound。
PD 分离(Prefill/Decode 解耦)将两类负载放到更合适的资源上,避免强强碰撞。
配合vLLM 的 PagedAttention(分块管理 KV 内存),可以有效降低 Cache 碎片化与浪费,让高并发 + 长上下文的场景更稳、更省、更快。
2.环境版本与依赖
2.1 基础环境
点击图片可查看完整电子表格
2.2 软件依赖
点击图片可查看完整电子表格
| 建议把vLLM与vLLM-ascend的 commit/tag 锁定到同一大版本,避免 API 漂移带来的兼容性问题。 |
|---|
3.环境搭建(要点版)
3.1 连通性与健康检查
| Bash# 设备与状态 npu-smi info # HCCL 链路(逐卡) for i in {0…15}; do hccn_tool -i $i -lldp -g | grep Ifname; done for i in {0…15}; do hccn_tool -i $i -link -g; done for i in {0…15}; do hccn_tool -i $i -net_health -g; done for i in {0…15}; do hccn_tool -i $i -netdetect -g; done for i in {0…15}; do hccn_tool -i $i -gateway -g; done # TLS 行为一致(PD 分离场景建议显式设置) for i in {0…15}; do hccn_tool -i $i -tls -g; done | grep switch for i in {0…15}; do hccn_tool -i $i -tls -s enable 0; done # 跨节点互通(从本节点 ping 对端 NPU IP) for i in {0…15}; do hccn_tool -i $i -ip -g; done for i in {0…15}; do hccn_tool -i $i -ping -g address ; done |
| :— |
3.2 容器建议(示例)
使用–privileged+–net=host,并挂载 Ascend 驱动/日志路径。
进入容器后,每次记得 source set_env.sh(toolkit 与 atb)。
3.3 安装 CANN / torch / torch-npu
CANN:安装 toolkit + kernels + nnal,磁盘预留 > 10GB;完成后:
| Bashsource /path/to/cann/ascend-toolkit/set_env.sh source /path/to/cann/nnal/atb/set_env.sh |
|---|
PyTorch & torch-npu:固定源,避免“依赖冲突找不到包”的老问题:
| Bashpip config set global.extra-index-url "https://download.pytorch.org/whl/cpu/ https://mirrors.huaweicloud.com/ascend/repos/pypi" pip install torchvision0.20.1 # 将自动装 torch2.5.1+cpu pip install torch-npu==2.5.1.post1.dev20250619 |
|---|
3.4 安装 vLLM 与 vLLM-ascend
| Bash# vLLM git clone https://github.com/vllm-project/vllm.git cd vllm && git checkout releases/v0.9.1 VLLM_TARGET_DEVICE=empty pip install -v -e . # vLLM-ascend cd … git clone https://github.com/vllm-project/vllm-ascend cd vllm-ascend && git checkout v0.9.1-dev pip install -v -e . |
|---|
| 克隆仓库如遇到 SSL 校验报错,可临时: |
|---|
4.PD 分离部署流程
4.1 生成 ranktable.json
在两台参与 PD 的机器上执行(IP 顺序:Prefill 在前,Decode 在后):
| Bashcd /home//vllm-ascend/examples/disaggregate_prefill_v1/ bash gen_ranktable.sh --ips 141.61.41.163 141.61.41.164 \ --npus-per-node 16 \ --network-card-name ens3f0 \ --prefill-device-cnt 16 \ --decode-device-cnt 16 |
|---|
关键参数说明:
--ips:PD 两端的宿主机 IP(Prefill 优先、Decode 其次) --network-card-name:承载通信的网卡名(ifconfig 查同 IP) --prefill/--decode-device-cnt:分配的 NPU 数量4.2 Prefill 节点脚本(P)
| Bash# 环境与端口 export HCCL_IF_IP=141.61.41.163 export GLOO_SOCKET_IFNAME=“ens3f0” export TP_SOCKET_IFNAME=“ens3f0” export HCCL_SOCKET_IFNAME=“ens3f0” export DISAGGREGATED_PREFILL_RANK_TABLE_PATH=/home//vllm-ascend/examples/disaggregate_prefill_v1/ranktable.json export OMP_PROC_BIND=false export OMP_NUM_THREADS=32 export VLLM_USE_V1=1 export VLLM_LLMDD_RPC_PORT=5559 # 拉起服务(Prefill 端) vllm serve /home/weight/deepseek/DeepSeek-V3.1-w8a8-rot-mtp \ --host 0.0.0.0 \ --port 20002 \ --data-parallel-size 1 \ --data-parallel-size-local 1 \ --api-server-count 1 \ --data-parallel-address 141.61.41.163 \ --data-parallel-rpc-port 13356 \ --tensor-parallel-size 16 \ --enable-expert-parallel \ --quantization ascend \ --seed 1024 \ --served-model-name deepseek \ --max-model-len 32768 \ --max-num-batched-tokens 32768 \ --max-num-seqs 64 \ --trust-remote-code \ --enforce-eager \ --gpu-memory-utilization 0.9 \ --kv-transfer-config \ ‘{“kv_connector”:“LLMDataDistCMgrConnector”,“kv_buffer_device”:“npu”,“kv_role”:“kv_producer”,“kv_parallel_size”:1,“kv_port”:“20001”,“engine_id”:“0”,“kv_connector_module_path”:“vllm_ascend.distributed.llmdatadist_c_mgr_connector”}’ |
|---|
| 关键项:–quantization ascend(w8a8 量化,避免 OOM)、–kv-transfer-config(PD 分离 KV 传输)。 |
|---|
4.3 Decode 节点脚本(D)
| Bash# 环境与端口 export HCCL_IF_IP=141.61.41.164 export GLOO_SOCKET_IFNAME=“ens3f0” export TP_SOCKET_IFNAME=“ens3f0” export HCCL_SOCKET_IFNAME=“ens3f0” export DISAGGREGATED_PREFILL_RANK_TABLE_PATH=/home//vllm-ascend/examples/disaggregate_prefill_v1/ranktable.json export OMP_PROC_BIND=false export OMP_NUM_THREADS=32 export VLLM_USE_V1=1 export VLLM_LLMDD_RPC_PORT=5659 # 拉起服务(Decode 端;注意更小的 max-model-len / batch) vllm serve /home/weight/deepseek/DeepSeek-V3.1-w8a8-rot-mtp \ --host 0.0.0.0 \ --port 20002 \ --data-parallel-size 1 \ --data-parallel-size-local 1 \ --api-server-count 1 \ --data-parallel-address 141.61.41.164 \ --data-parallel-rpc-port 13356 \ --tensor-parallel-size 16 \ --enable-expert-parallel \ --quantization ascend \ --seed 1024 \ --served-model-name deepseek \ --max-model-len 8192 \ --max-num-batched-tokens 256 \ --max-num-seqs 64 \ --trust-remote-code \ --gpu-memory-utilization 0.9 \ --kv-transfer-config \ ‘{“kv_connector”:“LLMDataDistCMgrConnector”,“kv_buffer_device”:“npu”,“kv_role”:“kv_consumer”,“kv_parallel_size”:1,“kv_port”:“20001”,“engine_id”:“0”,“kv_connector_module_path”:“vllm_ascend.distributed.llmdatadist_c_mgr_connector”}’ \ --additional-config \ ‘{“torchair_graph_config”:{“enabled”:true}}’ |
|---|
| Decode 端更关注RPS 与时延,因此 max-model-len / max-num-batched-tokens 可按场景调小。 |
|---|
4.4 分别拉起 P 与 D
| Bash# Prefill 节点 cd vllm-ascend/examples/disaggregate_prefill_v1/ bash npu16_vllm_ds_prefill.sh # Decode 节点 cd vllm-ascend/examples/disaggregate_prefill_v1/ bash npu16_vllm_ds_decode.sh |
|---|
看到 Application startup complete. 即表示就绪。
4.5 代理层(可选但推荐)
Prefill 机再开一个容器窗口,启动负载均衡代理:
| Bashsource /home//cmc/cann_8.2.rc1/ascend-toolkit/set_env.sh source /home//cmc/cann_8.2.rc1/nnal/atb/set_env.sh cd /home//vllm-ascend/examples/disaggregate_prefill_v1/ python load_balance_proxy_server_example.py \ --host 141.61.41.163 \ --port 1025 \ --prefiller-hosts 141.61.41.163 \ --prefiller-ports 20002 \ --decoder-hosts 141.61.41.164 \ --decoder-ports 20002 |
|---|
代理层负责把请求按阶段路由到 P / D,输出里会显示初始化成功的客户端数与服务地址。
5.功能验证与压测
5.1 API 验证
| Bashcurl http://141.61.41.163:1025/v1/completions \ -H “Content-Type: application/json” \ -d ‘{ “model”:“deepseek”, “prompt”:“how is it today”, “max_tokens”:50, “temperature”:0 }’ |
|---|
添加 -v 可查看更细日志;响应中 choices[0].text 为模型输出。
5.2 benchmark(vLLM 官方脚本)
| Bashsource /home//cmc/cann_8.2.rc1/ascend-toolkit/set_env.sh source /home//cmc/cann_8.2.rc1/nnal/atb/set_env.sh cd /home//vllm/benchmarks/ python benchmark_serving.py \ --backend vllm \ --dataset-name random \ --random-input-len 10 \ --random-output-len 100 \ --num-prompts 10 \ --ignore-eos \ --model deepseek \ --tokenizer /home/weight/deepseek/DeepSeek-V3.1-w8a8-rot-mtp \ --host 141.61.41.163 \ --port 1025 \ --endpoint /v1/completions \ --max-concurrency 4 \ --request-rate 4 |
|---|
| 关注指标:平均时延、P99、吞吐(req/s 或 tok/s)。对比PD 混部 vs PD 分离,一般在中高并发下分离更稳。 |
|---|
6.易错点与快速修复
(1)torch-npu 找不到可用版本
现象:No matching distribution found for torch-npu
原因:源不对/被墙。
解法:
| Bashpip uninstall torch -y pip config set global.trusted-host “download.pytorch.org mirrors.huaweicloud.com mirrors.aliyun.com” pip config set global.extra-index-url "https://download.pytorch.org/whl/cpu/ https://mirrors.huaweicloud.com/ascend/repos/pypi" pip install torchvision0.20.1 pip install torch-npu2.5.1.post1.dev20250619 |
|---|
(2)依赖冲突:torch-npu 与 torch 版本不兼容
现象:Cannot install torch-npu==2.5.1.post1 and torch>=2.5.1 …
解法:
| Bashpip uninstall torch2.5.1 torch-npu2.5.1.post1.dev20250619 -y pip cache purge pip config unset global.extra-index-url pip config set global.extra-index-url "https://download.pytorch.org/whl/cpu/ https://mirrors.huaweicloud.com/ascend/repos/pypi" pip install torch2.5.1 pip install torch-npu2.5.1.post1.dev20250619 pip show torch torch-npu | grep Version |
| :— |
(3)NPU OOM
现象:RuntimeError: NPU out of memory …
根因:量化未生效或 batch 过大。
解法:启动参数加 --quantization ascend;调小 --max-model-len / --max-num-batched-tokens / --max-num-seqs。
(4)aclnnQuantMatmulV4 类型不支持
现象:Tensor scale not implemented for DT_FLOAT16 …
根因:模型 torch_dtype 与内核期望不符。
解法:改模型 config.json:“torch_dtype”:“bfloat16”。
(5)HCCL 初始化失败
现象:HCCL function error … error code is 6
根因:HCCL_IF_IP 与本机 IP 不一致 / ranktable 不匹配。
解法:修正 HCCL_IF_IP,复查 ranktable.json 与实际卡数/网卡。
7.优化建议(进阶)
KV 策略:长文本场景适当提高 --max-model-len,但要与 Decode 侧并发上限平衡;观察 PagedAttention 的 page 命中情况,避免频繁迁移。
并行度:–tensor-parallel-size 与模型结构相关;EP(专家并行)建议先按官方实践设置,压测后再做微调。
IRQ/绑核:Decode 端对延迟敏感,建议业务线程与高频 IRQ 分核(同 NUMA)。
代理层:把路由逻辑从业务进程剥离,便于后续横向扩缩(多 P / 多 D)。
故障演练:压测时主动制造 Decode 端抖动,观察代理的重试/熔断策略是否生效。
8.小结
PD 分离让 Prefill 的计算与 Decode 的访存/带宽压力“各归其位”,避免互相争抢。
vLLM 的 PagedAttention把 KV Cache 的占用与碎片化压得更稳,适合长上下文与高并发。
在vLLM-ascend上部署DeepSeek-V3-w8a8的关键,是版本对齐、量化生效、HCCL 正确与KV 传输配置。
按文中流程走一遍,基本能做到“可复现、可压测、可扩展”。剩下的,就是基于你的业务画像做参数的工程化微调了。