vLLM适配昇腾NPU:DeepSeek-V3 PD分离部署完整流程
做过大模型推理优化的朋友都知道,Prefill和Decode这两个阶段的性质完全不同:Prefill阶段就像是读完整本书做笔记——需要把用户输入的完整prompt编码成隐藏状态,同时生成KV Cache。这个过程计算量大,吃算力。Decode阶段更像是一个字一个字往外蹦——每次只生成一个token,一直重复到结束。这个过程主要瓶颈在显存带宽,属于典型的访存密集型任务。两个阶段混在一起跑,就会出现资
一、为什么要做PD分离?
做过大模型推理优化的朋友都知道,Prefill和Decode这两个阶段的性质完全不同:
Prefill阶段就像是读完整本书做笔记——需要把用户输入的完整prompt编码成隐藏状态,同时生成KV Cache。这个过程计算量大,吃算力。
Decode阶段更像是一个字一个字往外蹦——每次只生成一个token,一直重复到结束。这个过程主要瓶颈在显存带宽,属于典型的访存密集型任务。
两个阶段混在一起跑,就会出现资源利用不均的问题。PD分离部署方案把这两个阶段拆开,让Prefill和Decode各自在最适合的硬件环境中运行,配合vLLM的PagedAttention技术管理KV缓存,能大幅提升整体吞吐。
本文记录了在昇腾NPU平台上部署DeepSeek-V3-w8a8量化模型的完整过程,希望能帮到正在做类似工作的同学。
二、硬件与软件环境
硬件配置
| 项目 | 配置 |
|---|---|
| 硬件平台 | 2台Atlas 800I A2服务器(每台16卡×64GB) |
| 操作系统 | Ubuntu 22.04 |
| 驱动版本 | 25.2.0 |
| Python版本 | 3.11 |
软件版本清单
| 组件 | 版本 | 说明 |
|---|---|---|
| CANN | 8.2.RC1 | 昇腾计算架构 |
| torch | 2.5.1+cpu | CPU版本 |
| torch_npu | 2.5.1.post1.dev20250619 | NPU适配版本 |
| torchvision | 0.20.1 | 随torch自动安装 |
| vLLM | 0.9.1 | 推理引擎 |
| vLLM-ascend | 0.9.1-dev | NPU适配版本 |
三、环境准备工作
3.1 NPU设备检查
在开始部署前,先确认NPU设备和网络状态正常。下面这组命令建议都跑一遍:
# 查看NPU设备状态
npu-smi info
# 检查物理连接
for i in {0..15}; do hccn_tool -i $i -lldp -g | grep Ifname; done
# 确认以太网端口状态(应该都是up)
for i in {0..15}; do hccn_tool -i $i -link -g ; done
# 检查网络健康状况(应该显示success)
for i in {0..15}; do hccn_tool -i $i -net_health -g ; done
# 查看IP配置
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配置一致性
for i in {0..15}; do hccn_tool -i $i -tls -g ; done | grep switch
# 关闭TLS校验(这一步很重要)
for i in {0..15};do hccn_tool -i $i -tls -s enable 0;done
# 获取各NPU的IP地址
for i in {0..15}; do hccn_tool -i $i -ip -g;done
# 测试跨节点连通性(替换<NPU-IP>为实际IP)
for i in {0..15}; do hccn_tool -i $i -ping -g address <NPU-IP>;done
3.2 创建Docker容器
容器环境能避免很多依赖冲突的问题。如果不是root用户,先切换:
sudo su - root
mkdir /home/<your_name>

出现如上所示结果,然后输入密码后,mkdir /home/<your_name>输入指令,这里替换路径中的<your_name>,换成我们自己的
创建容器(注意替换路径中的<your_name>):
docker run -it --privileged --name=vllm_deepseek_pd \
--net=host --shm-size=500g \
--device=/dev/davinci_manager \
--device=/dev/hisi_hdc \
--device=/dev/devmm_svm \
--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 \
-v /usr/local/Ascend/driver:/usr/local/Ascend/driver \
-v /usr/local/Ascend/add-ons/:/usr/local/Ascend/add-ons/ \
-v /usr/local/sbin/:/usr/local/sbin/ \
-v /var/log/npu/slog/:/var/log/npu/slog \
-v /usr/local/dcmi:/usr/local/dcmi \
-v /usr/local/bin/npu-smi:/usr/local/bin/npu-smi \
-v /etc/ascend_install.info:/etc/ascend_install.info \
-v /var/log/npu/profiling/:/var/log/npu/profiling \
-v /var/log/npu/dump/:/var/log/npu/dump \
-v /var/log/npu/:/usr/slog \
-v /etc/hccn.conf:/etc/hccn.conf \
-v /home/:/home \
-w /home/<your_name> \
mindie:2.1.RC1-800I-A2-py311-ubuntu22.04-x86_64 \
/bin/bash
进入容器后配置网络代理,用curl www.baidu.com测试网络是否正常。
3.3 安装软件依赖
安装CANN套件
从昇腾社区下载三个安装包:
- Ascend-cann-toolkit_*.run (开发套件)
- Ascend-cann-kernels-*.run (算子包)
- Ascend-cann-nnal_*.run (神经网络加速库)
安装前确保目标目录有10GB以上可用空间:
chmod a+x Ascend-cann-kernels-910b_8.2.RC1_linux-x86_64.run
chmod a+x Ascend-cann-nnal_8.2.RC1_linux-x86_64.run
chmod a+x Ascend-cann-toolkit_8.2.RC1_linux-x86_64.run
# 先做检查
./Ascend-cann-toolkit_8.2.RC1_linux-x86_64.run --check
./Ascend-cann-toolkit_8.2.RC1_linux-x86_64.run --install --install-path=/home/<your_name>/cann_8.2.rc1
./Ascend-cann-kernels-910b_8.2.RC1_linux-x86_64.run --check
./Ascend-cann-kernels-910b_8.2.RC1_linux-x86_64.run --install --install-path=/home/<your_name>/cann_8.2.rc1
./Ascend-cann-nnal_8.2.RC1_linux-x86_64.run --check
./Ascend-cann-nnal_8.2.RC1_linux-x86_64.run --install --install-path=/home/<your_name>/cann_8.2.rc1
# 配置环境变量(每次进容器都要执行)
source /home/<your_name>/cann_8.2.rc1/ascend-toolkit/set_env.sh
source /home/<your_name>/cann_8.2.rc1/nnal/atb/set_env.sh
安装PyTorch和torch_npu
先配置pip镜像源,然后安装:
pip config set global.extra-index-url "https://download.pytorch.org/whl/cpu/ https://mirrors.huaweicloud.com/ascend/repos/pypi"
pip install attrs cython numpy==1.26.4 decorator sympy==1.13.1 \
cffi pyyaml pathlib2 psutil protobuf==6.31.1 scipy requests absl-py
pip install torchvision==0.20.1 # 会自动安装torch==2.5.1+cpu
pip install torch-npu==2.5.1.post1.dev20250619
安装vLLM和vLLM-ascend
从GitHub拉取代码并安装:
# 安装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证书问题,执行:
export GIT_SSL_NO_VERIFY=1
git config --global http.sslVerify false
四、部署流程
4.1 生成ranktable配置文件
在两台设备上都执行这个脚本,生成集群拓扑配置:
cd /home/<your_name>/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: P节点和D节点的IP,P在前D在后npus-per-node: 每台机器的NPU数量network-card-name: 网卡名称(用ifconfig查看)prefill-device-cnt: Prefill用的卡数decode-device-cnt: Decode用的卡数
4.2 编写Prefill启动脚本
在P节点创建start_prefill.sh:
#!/bin/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/<your_name>/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/models/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"
}'
4.3 编写Decode启动脚本
在D节点创建start_decode.sh:
#!/bin/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/<your_name>/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服务
vllm serve /home/models/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}}'
4.4 启动服务
分别在两个节点执行启动脚本:
# P节点
bash start_prefill.sh
# D节点
bash start_decode.sh
看到Application startup complete.就说明启动成功了。
4.5 启动负载均衡代理
在P节点开一个新的终端窗口,先配置环境变量:
source /home/<your_name>/cann_8.2.rc1/ascend-toolkit/set_env.sh
source /home/<your_name>/cann_8.2.rc1/nnal/atb/set_env.sh
然后运行代理服务:
cd /home/<your_name>/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
启动成功后会显示初始化的prefill和decode客户端数量:
五、功能验证
5.1 API接口测试
开一个新的终端,发送测试请求:
curl 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参数可以看详细的请求响应过程。返回结果中的choice/text就是模型生成的文本:
5.2 性能压测
在P节点运行benchmark脚本:
source /home/<your_name>/cann_8.2.rc1/ascend-toolkit/set_env.sh
source /home/<your_name>/cann_8.2.rc1/nnal/atb/set_env.sh
cd /home/<your_name>/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/models/DeepSeek-V3.1-w8a8-rot-mtp \
--host 141.61.41.163 \
--port 1025 \
--endpoint /v1/completions \
--max-concurrency 4 \
--request-rate 4
测试结果会显示吞吐量、延迟等关键指标:
六、踩过的坑
问题1: 找不到torch-npu包
使用pip 25.1.1安装时提示找不到匹配的版本:
解决办法: 配置正确的镜像源
pip uninstall torch
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 torchvision==0.20.1
pip install torch-npu==2.5.1.post1.dev20250619
问题2: torch和torch-npu依赖冲突
安装vllm-ascend时报错:Cannot install torch-npu==2.5.1.post1 and torch>=2.5.1 because these package versions have conflicting dependencies.
解决办法: 清理环境后重装
pip uninstall torch==2.5.1 torch-npu==2.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 torch==2.5.1
pip install torch-npu==2.5.1.post1.dev20250619
# 验证安装
pip show torch torch-npu | grep Version
问题3: NPU显存溢出
启动服务时报错:RuntimeError: NPU out of memory. Tried to allocate 898.00 MiB...
原因: 没有按量化模式加载模型
解决办法: 在vllm serve命令中加上--quantization ascend
问题4: 量化算子不支持float16
报错信息:Tensor scale not implemented for DT_FLOAT16, should be in dtype support list [DT_UINT64,DT_BFLOAT16,DT_INT64,DT_FLOAT,].

原因: aclnnQuantMatmulV4算子不支持float16类型
解决办法: 修改模型config.json文件,把torch_dtype从float16改成bfloat16
问题5: HCCL通信初始化失败
报错:RuntimeError: createHCCLComm:torch_npu/csrc/distributed/ProcessGroupHCCL.cpp:2166 HCCL function error...
原因: HCCL_IF_IP环境变量配置错误
解决办法: 检查并修正启动脚本中的HCCL_IF_IP,确保和本机IP一致
总结
PD分离部署对大模型推理性能提升确实有明显效果,但配置过程比较繁琐,需要注意的点也很多。希望这份实战记录能帮大家少踩一些坑。
如果在部署过程中遇到其他问题,建议先查看官方文档和社区讨论,很多常见问题都有解决方案。
更多推荐



所有评论(0)