PD分离
特性介绍
PD分离(Prefill-Decode Disaggregation)是一种围绕KV Cache的分离式解码部署方式,其将Prefill和Decode阶段部署在两个独立集群,充分利用CPU、DRAM和SSD资源来实现KV Cache的分解缓存,旨在满足与延迟相关的服务级别目标(SLO)下最大化吞吐量,破解推理服务性能瓶颈,在长上下文输入的场景中表现出高效性能。
应用场景
使用基于KV Cache中心的分离式推理框架,将Prefill阶段和Decode阶段分离部署在独立集群。
能力范围
PD分离能充分利用CPU、DRAM和SSD资源,提高吞吐量,尤其在长上下文输入的场景中表现出高效性能。
亮点特征
-
batch整合:
原有的串行队列中,无论request中的prompt长短,Prefill节点都是执行完一个request,才会去队列中取出下一个request。针对用户输入较短的场景,采用串行的执行方式,往往会存在大量的NPU算力浪费。我们根据用户的输入长度与实际的负载,对队列消费机制进行整合。例如将长度小于的1024的request,通过batch合并的方式,将多个小batch或者多个batch进行合并,从而提升执行的并行度,并提升整体吞吐的指标。
-
PD负载感知:
前缀缓存命中的绝对预填充长度≤预设阈值。一方面,如果请求的预填充长度很短,则可以通过将分块预填充请求与正在进行的解码请求搭载在解码引擎中进行有效计算。另一方面,如果前缀缓存命中很长,则预填充将成为内存bound,而不是算力bound,因此可以在解码引擎中更有效地计算。 预填充队列中的远程预填充请求数<预设阈值。当prefill队列有大量的请求时,说明prefill worker滞后,最好在本地进行计算,直到更多的prefill worker加入。
实现原理
PD分离采用以KV Cache为核心的分离式推理框架,其将Prefill和Decode两个阶段部署在两个独立集群,针对两阶段的资源需求分配资源,最终实现低延迟与高吞吐量的平衡。
与相关特性的关系
- Mooncake:Mooncake作为PD分离过程中的通信工具,能够Prefill和Decode阶段之间快速传输KV Cache等数据。
- vLLM:vLLM可作为PD分离架构中Prefill或Decode阶段的推理计算组件,提供推理接口。
安装
前提条件
需要对共享存储挂载及参数面连通性进行检查,具体如下。
-
共享存储挂载
- 使用
ll /mnt
查询存储是否自动挂载上。 - 若没挂载上,使用
mount -t dpc /kdxf /mnt
进行挂载。
- 使用
-
参数面连通性
-
检查网口up/down状态:
for i in {0..7}; do hccn_tool -i $i -link -g; done
,网口没有down的情况则为正常。 -
检查网口是否有闪断:
for i in {0..7}; do hccn_tool -i $i -link_stat -g; done
,网口没有闪断则为正常。 -
检查tls配置:
for i in {0..7};do hccn_tool -i $i -tls -g|grep "tls switch";done
,正常情况如下:若存在不为0的情况:
for i in {0..7};do hccn_tool -i $i -tls -s enable 0;done
,将tls配置成0。 -
执行如下命令关闭防火墙。
systemctl stop firewalld
systemctl disable firewalld -
参数面网络连通性检查方法:尝试使用集群中所有的卡ping同一张卡的IP地址。
5.1 在一台服务器上执行
cat /etc/hccn.conf
,记录一个集群环境下的device ip
,后续步骤将该ip表示为【ip】
。5.2 当前使用的服务器上都执行,
for i in {0..7}; do hccn_tool -i $i -ping -g address 【ip】; done
。5.3 若都能ping通则参数面网络连通性没有问题。
-
开始安装
-
镜像下载。
下载Ubuntu 22.04版本镜像
mindie_dev-2.1.RC1.B152-800I-A2-py311-ubuntu22.04-aarch64.tar.gz
,上传至服务器中。 -
启动容器。
2.1 执行如下命令进入镜像所在目录加载镜像。
docker load -i mindie-XXX.tar.gz
2.2 执行如下命令查看已加载镜像id。
docker images
2.3 执行如下命令启动容器。
docker run --name openfuyao_pd -it -d --net=host --shm-size=500g \
--privileged=true \
-w /home \
--device=/dev/davinci_manager \
--device=/dev/hisi_hdc \
--device=/dev/devmm_svm \
--entrypoint=bash \
-v /mnt:/mnt \
-v /data:/data \
-v /dev:/dev \
-v /usr/local/Ascend/driver:/usr/local/Ascend/driver \
-v /usr/local/dcmi:/usr/local/dcmi \
-v /usr/local/bin/npu-smi:/usr/local/bin/npu-smi \
-v /usr/local/sbin:/usr/local/sbin \
-v /home:/home \
-v /tmp:/tmp \
-v /opt:/opt \
-v /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime \
-v XXX \
bc6711a1ef08 #这里用之前查看的镜像id -
git拉取。
3.1 执行如下命令进入容器内部。
docker exec -it openfuyao_pd bash #openfuyao_pd替换为实际的容器id或容器名,容器信息可以docker ps查看
3.2 执行如下命令配置代理并git拉取。
# 网络配置
export http_proxy=http://[account]:[password]@proxyhk.huawei.com:8080
export https_proxy=http://[account]:[password]@proxyhk.huawei.com:8080
export no_proxy=127.0.0.1,localhost,local,.local
git config --global http.sslVerify false
# 下载Mooncake
git clone https://github.com/AscendTransport/Mooncake
# 下载vLLM
git clone https://github.com/vllm-project/vllm
# 下载vllm-ascend
git clone https://gitcode.com/openFuyao/vllm-ascend -
Mooncake安装。
打开拉取文件夹下Mooncake/scripts/ascend/dependencies_ascend.sh脚本文件,找到如下两行whl包的安装代码,将其注释掉,避免重复安装。
pip install mooncake-wheel/dist/*.whl --force
echo -e "Mooncake wheel pipinstall successfully."之后运行安装脚本。
cd Mooncake/scripts/ascend
#注释掉最后两行whl包的安装,重复安装会报错
bash dependencies_ascend.sh -
vLLM安装。
执行如下命令进入vllm目录,运行安装脚本。
cd vllm
VLLM_TARGET_DEVICE=empty pip install -v -e . -
vllm-ascend安装。
进入vllm-ascend目录,修改
requirements.txt
、pyproject.toml
两个文件的torch-nup
版本为torch-npu==2.7.1rc1
,之后运行以下安装脚本。cd vllm-ascend/
#修改requirements.txt、pyproject.toml
COMPILE_CUSTOM_KERNELS=0 pip install -v -e ./可以通过如下命令查看是否安装成功。
pip list | grep vllm
若安装成功,会有类似的如下两行输出。
vllm 0.10.2rc2.dev7+g7c8271cd1.empty
vllm_ascend 0.1.dev789+g9b418ede4.d20250902 -
torch-npu安装。
下载对应版本的torch_npu包:
torch_npu-2.7.1.dev20250724-cp311-cp311-manylinux_2_28_aarch64.whl
并上传至服务器。在对应目录执行以下安装命令。
pip install --no-index --no-deps --force-reinstall torch_npu**
使用PD分离拉起实例
前提条件
已在容器中安装Mooncake,vLLM及vllm-ascend。
背景信息
PD分离将Prefill和Decode阶段部署在两个独立集群,以实现资源的充分利用和吞吐量的提高。
使用限制
在拉起过程中,每个Prefill和Decode实例使用的Port不能冲突,且Prefill实例的tp_size
应不小于Decode的tp_size
。
操作步骤
-
PD分离拉起。
1.1 准备脚本run_prefill.sh、run_decode.sh。注意替换模型文件路径
./Qwen3-8B
为实际文件路径。run_prefill.sh
export HCCL_EXEC_TIMEOUT=204
export HCCL_CONNECT_TIMEOUT=120
export HCCL_IF_IP=0.0.0.0
export GLOO_SOCKET_IFNAME="eth0"
export TP_SOCKET_IFNAME="eth0"
export HCCL_SOCKET_IFNAME="eth0"
export ASCEND_RT_VISIBLE_DEVICES=0,1
export VLLM_USE_V1=1
export LD_LIBRARY_PATH=/usr/local/Ascend/ascend-toolkit/latest/python/site-packages:$LD_LIBRARY_PATH
echo "HCCL_IF_IP=$HCCL_IF_IP"
vllm serve ./Qwen3-8B \
--host 0.0.0.0\
--port 8107 \
--tensor-parallel-size 2\
--seed 1024 \
--max-model-len 2000 \
--max-num-batched-tokens 2000 \
--trust-remote-code \
--enforce-eager \
--data-parallel-size 1 \
--data-parallel-address localhost \
--data-parallel-rpc-port 9100 \
--gpu-memory-utilization 0.8 \
--kv-transfer-config \
'{"kv_connector": "MooncakeConnectorV1",
"kv_buffer_device": "npu",
"kv_role": "kv_producer",
"kv_parallel_size": 1,
"kv_port": "20001",
"engine_id": "0",
"kv_rank": 0,
"kv_connector_module_path": "vllm_ascend.distributed.mooncake_connector",
"kv_connector_extra_config": {
"prefill": {
"dp_size": 1,
"tp_size": 2
},
"decode": {
"dp_size": 1,
"tp_size": 2
}
}
}'run_decode.sh
export HCCL_EXEC_TIMEOUT=204
export HCCL_CONNECT_TIMEOUT=120
export HCCL_IF_IP=0.0.0.0
export GLOO_SOCKET_IFNAME="eth0"
export TP_SOCKET_IFNAME="eth0"
export HCCL_SOCKET_IFNAME="eth0"
export ASCEND_RT_VISIBLE_DEVICES=2,3
export VLLM_USE_V1=1
export LD_LIBRARY_PATH=/usr/local/Ascend/ascend-toolkit/latest/python/site-packages:$LD_LIBRARY_PATH
echo "HCCL_IF_IP=$HCCL_IF_IP"
vllm serve ./Qwen3-8B \
--host 0.0.0.0 \
--port 8207 \
--tensor-parallel-size 2\
--seed 1024 \
--max-model-len 2000 \
--max-num-batched-tokens 2000 \
--trust-remote-code \
--enforce-eager \
--data-parallel-size 1 \
--data-parallel-address localhost \
--data-parallel-rpc-port 9100 \
--gpu-memory-utilization 0.8 \
--no-enable-prefix-caching \
--kv-transfer-config \
'{"kv_connector": "MooncakeConnectorV1",
"kv_buffer_device": "npu",
"kv_role": "kv_consumer",
"kv_parallel_size": 1,
"kv_port": "20002",
"engine_id": "1",
"kv_rank": 1,
"kv_connector_module_path": "vllm_ascend.distributed.mooncake_connector",
"kv_connector_extra_config": {
"prefill": {
"dp_size": 1,
"tp_size": 2
},
"decode": {
"dp_size": 1,
"tp_size": 2
}
}
}'1.2 执行如下命令分别完成拉起。
bash run_prefill.sh
bash run_decode.sh1.3 创建新端口开启服务,注意
prefiller-hosts
、prefiller-ports
、decoder-hosts
、decoder-ports
与脚本中设置对应。cd vllm-ascend/examples/disaggregated_prefill_v1/
python load_balance_proxy_server_example.py --host 0.0.0.0 --prefiller-hosts 127.0.0.1 --prefiller-ports 8107 --decoder-hosts 127.0.0.1 --decoder-ports 8207 --port 9090 -
服务拉起验证
创建新端口测试。注意替换模型文件路径
./Qwen3-8B
为实际文件路径,测试访问的Port需要与开启服务时指定的Port保持一致(示例中均为9090)。curl -v -s http://127.0.0.1:9090/v1/completions -H "Content-Type: application/json" -d '{"model": "./Qwen3-8B","prompt": "你好,你是谁?","max_tokens": 256}'
出现类似回答说明配置成功。
后续操作
-
如需开启batch整合,需要在Prefill实例的拉起脚本中添加以下环境变量。
export BATCH_BY_REQUEST_LENGTH="true"
并在Prefill实例的拉起脚本的
vllm serve
指令中添加以下参数。--scheduling-policy "priority"
-
如需修改PD分离拉起实例中的其他配置,请参考 vllm-ascend/examples/disaggregated_prefill_v1/mooncake_connector_deployment_guide.md at main · vllm-project/vllm-ascend · GitHub。