PD分离部署实践:DeepSeek-V3-w8a8与 vLLM 的技术融合之路

147 阅读10分钟

一、背景与意义

熟悉大模型推理的应该知道其在两个核心阶段存在显著差异:

  • Prefill 阶段: 当用户输入完整序列(如 prompt)时,模型需要一次性对整个序列进行处理,计算所有 token 的注意力权重、进行矩阵乘法(如 QKV 计算、输出投影等)。由于输入序列长度通常较长(可能达千级 token),此阶段涉及大量并行的矩阵运算,计算量随序列长度呈平方增长(注意力机制的复杂度),因此是典型的计算密集型任务。同时,该阶段还会生成初始的 KV Cache(键值缓存),用于后续解码阶段复用,避免重复计算。
  • Decode 阶段:在生成输出文本时,模型每次仅基于上一个生成的 token 和历史 KV Cache 计算下一个 token,输入序列长度固定为 1(当前 token)。此时计算量大幅减少,但需要频繁读取和更新 KV Cache(随着生成序列增长,KV Cache 的容量线性增加),且每次生成都需等待前一次结果,并行性极低。因此,该阶段更依赖内存带宽和延迟,是访存密集型任务。

相较于 PD 混部,PD 分离的模型部署方式通过将 prefill 和 decode 阶段解耦,可有效提升资源利用率。而 vLLM的 PagedAttention 技术能高效管理两阶段的 KV 缓存,结合 PD 分离可进一步减少内存浪费。本文主要记录了 DeepSeek-V3-w8a8 模型在 vLLM 环境下的 PD 分离部署过程。

二、环境版本与依赖清单

基础环境配置

软硬件版本或款型
硬件平台两台G8600(16卡*64GB)
操作系统ubuntu 22.04
驱动版本25.2.0
python3.11

软件依赖版本

组件版本备注
CANN8.2.RC1
torch2.5.1+cpu对应torchvision 0.20.1
torch_npu2.5.1.post1.dev20250619
vLLM0.9.1需与vLLM-Ascend版本一致
vLLM-ascend0.9.1-dev

三、环境搭建准备

1. 环境检查与验证

在部署之前环境检查与验证是所必须的,以下环境检查脚本可以确保物理连接正常、网络健康、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# 检查NPU底层tls校验行为一致性
for i in {0..15}; do hccn_tool -i $i -tls -g ; done | grep switch
​
# NPU底层tls校验行为置0
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# 检查能否跨节点ping通(从本节点ping其它节点上的NPU)
for i in {0..15}; do hccn_tool -i $i -ping -g address <NPU-IP>;done

2. 容器环境配置

  1. 如果不是以root身份登录设备,在登录后先切换到root
sudo su - root

2. 在home下面创建个人目录

mkdir /home/<name>

3. 创建容器(需删除注释)

docker run -it --privileged --name=test_vllm_ds_dp --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/<name> \
vllm-ascend:2.1.RC1-800I-A2-py311-ubuntu22.04-x86_64 \
/bin/bash

如果找不到镜像vllm-ascend:2.1.RC1-800I-A2-py311-ubuntu22.04-x86_64可以将其下载到本地

  1. 进入容器
docker exec -it test_vllm_ds_dp bash

5. 完成网络代理配置,通过curl www.baidu.com校验网络是否正常

可以正常返回百度首页的 html 信息则代表网络正常

3. 软件安装流程

(1)安装CANN

下载并检查toolkitkernelsnnal安装包,推荐使用 8.2.RC1 版本。

  1. 赋予执行权限
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

2. 分别对其先进行安装包完整性检查,然后安装到指定目录

./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/<name>/cmc/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/<name>/cmc/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/<name>/cmc/cann_8.2.rc1

3. 添加环境变量。注意每次重新进入容器都需要配置环境变量

source /home/<name>/cmc/cann_8.2.rc1/ascend-toolkit/set_env.sh
source /home/<name>/cmc/cann_8.2.rc1/nnal/atb/set_env.sh

无需将<font style="color:rgba(0, 0, 0, 0.85);background-color:rgba(0, 0, 0, 0.04);">kernels</font>添加环境变量,<font style="color:rgba(0, 0, 0, 0.85);background-color:rgba(0, 0, 0, 0.04);">toolkit</font>的环境变量脚本就已经包含了对其算子库路径的引用。

(2)安装torch和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 torch==2.5.1
pip install torchvision==0.20.1 #  安装时会自动安装torch==2.5.1+cpu
pip install torch-npu==2.5.1.post1.dev20250619

(3)安装vLLM

cd ../
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 .

(4)安装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 .

说明:如果在克隆git仓库时遇到SSL证书验证失败的问题,则关闭证书校验。

export GIT_SSL_NO_VERIFY=1
git config --global http.sslVerify false

到此为止,环境搭建就完成了,下面就要进行具体的模型部署了。

四、模型部署流程

1. 创建ranktable.json

在所有用于PD分离的设备上执行以下脚本,生成ranktable。

cd /home/<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:用于PD分离的设备IP。P节点在前,D节点在后
  • npus-per-node:每个节点的npu数量
  • network-card-name:网卡名称。获取方式:ifconfig,查找ip和设备ip相同的端口名称
  • prefill-device-cnt:用于prefill的卡数
  • decode-device-cnt:用于decode的卡数

2. 配置并拉起 Prefill 节点

  1. 设置环境变量
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/<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

2. 拉起服务

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"
}'

3. 配置并拉起 Decode 节点

  1. 设置环境变量
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/<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

2. 拉起服务

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}}'

回显Application startup complete. 表示启动成功。

4. 运行代理

prefill 的机器上新建容器交互窗口,运行 load_balance_proxy_server_example.py

source /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

回显 Application startup complete.表示启动成功。回显信息中包含成功初始化的prefill客户端、decode客户端数量和服务化地址。

到这里就完成了模型的部署了。

五、模型验证

1. API接口测试

在prefill的机器上新建容器交互窗口,发送Completions 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为模型输出的文本。

2. benchmark测试

在prefill侧运行脚本:

source /home/<name>/cmc/cann_8.2.rc1/ascend-toolkit/set_env.sh
source /home/<name>/cmc/cann_8.2.rc1/nnal/atb/set_env.sh
​
cd /home/<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/weight/deepseek/DeepSeek-V3.1-w8a8-rot-mtp --host 141.61.41.163 --port 1025 --endpoint /v1/completions --max-concurrency 4 --request-rate 4

获取benchmark测试结果:

六、遇见的坑

(1)无法找到满足要求的torch-npu版本

问题现象:使用pip 25.1.1版本安装时,提示无法找到满足要求的torch-npu版本。 产生原因:使用的镜像地址不合适。 解决方法:指定使用的镜像地址,重新安装。

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 torch==2.5.1
​
pip install torchvision==0.20.1 #  安装时会自动安装torch==2.5.1+cpu
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.

产生原因:可能是安装torch、torch-npu时,使用的源和期望不一致。 解决方法:重新指定使用的镜像地址,重新安装。

pip uninstall torch==2.5.1 torch-npu==2.5.1.post1.dev20250619 -y #  卸载已安装的torch和torch-npu
pip cache purge #  清除缓存和构建环境
pip config unset global.extra-index-url #  重新设置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 #  重新下载torch和torch-npu
pip install torch-npu==2.5.1.post1.dev20250619
# 查看安装的torch和torch-npu版本
pip show torch torch-npu | grep Version

(3)拉起服务时报 NPU out of memory

问题现象:报错信息为 RuntimeError: NPU out of memory. Tried to allocate 898.00 MiB (NPU 15; 60.96 GiB total capacity; 59.80 GiB already allocated; 59.80 GiB current active; 804.00 MiB free; 59.83 GiB reserved in total by PyTorch) If reserved memory is >> allocated memory try setting max_split_size_mb to avoid fragmentation. 产生原因:未按量化方式加载模型参数。 解决方法:用vllm serve拉起服务时,添加--quantization ascend。

(4)拉起服务时报 NPU function error: call aclnnQuantMatmulV4 failed

问题现象:报错信息为 Tensor scale not implemented for DT_FLOAT16, should be in dtype support list [DT_UINT64,DT_BFLOAT16,DT_INT64,DT_FLOAT,]. 产生原因:模型参数类型和aclnnQuantMatmulV4接口支持的参数类型不符。 解决方法:打开deepseek模型的config.json文件,torch_dtype由float16改为bfloat16。

(5)拉起服务时报 HCCL function error

问题现象:报错信息为 RuntimeError: createHCCLComm:torch_npu/csrc/distributed/ProcessGroupHCCL.cpp:2166 HCCL function error: HcclGetRootInfo(&hcclID), error code is 6;ERR02200 DIST call hccl api failed. 产生原因:HCCL_IF_IP与本机IP不符。 解决方法:修改脚本中的HCCL_IF_IP环境变量。

七、总结

这就是完整的 DP 分离部署的流程了,DP 分离部署后确实对大模型的效率进行了不小的提升,利用 Prefill 和 Decode 两阶段的计算/通信特征的差异特点,为了提升性能和资源利用效率,通过PD分离部署方案将 Prefill 和 Decode 分别部署在不同规格和架构的集群中,并且配合服务层的任务调度,在提供更好用户体验的前提下,可以充分提升算力利用率。

如果你也感兴趣的话,欢迎来尝试亲手部署一个 DP 分离的 LLM 大模型吧。

注明:昇腾PAE案例库对本文写作亦有帮助。