vLLM-ascend 下的 PD 分離實戰:從DeepSeek-V3-w8a8模型到壓測,一次把坑踩完

Prefill 計算密集、Decode 訪存密集——這對天然割裂的階段,決定了大模型推理並非一鍋燉。

把兩者解耦(PD 分離)+ 用 vLLM 的 PagedAttention 精準管控 KV Cache,是目前在昇騰場景下把吞吐與成本同時打上去的可靠路徑。

我們就用 DeepSeek-V3-w8a8 為例,完整記錄在 vLLM-ascend 上落地 PD 分離 的過程與最佳實踐,並附常見報錯與處理清單,幫助你少走彎路。

<font style="color:#3370FF;">1. </font>背景與意義

Prefill:把完整輸入編碼為隱藏狀態並生成初始 KV Cache,計算密集、顯存瞬時佔用高。

Decode:一次生成一個 token,強依賴 KV Cache 讀寫,訪存/帶寬密集、鏈路易 HostBound。

PD 分離(Prefill/Decode 解耦)將兩類負載放到更合適的資源上,避免強強碰撞。
配合 vLLM 的 PagedAttention(分塊管理 KV 內存),可以有效降低 Cache 碎片化與浪費,讓 高併發 + 長上下文 的場景更穩、更省、更快。

<font style="color:#3370FF;">2. </font>環境版本與依賴

2.1 基礎環境

點擊圖片可查看完整電子表格

2.2 軟件依賴

點擊圖片可查看完整電子表格

<font style="color:rgb(100, 106, 115);">建議把 </font><font style="color:rgb(100, 106, 115);">vLLM</font><font style="color:rgb(100, 106, 115);"> 與 </font><font style="color:rgb(100, 106, 115);">vLLM-ascend</font><font style="color:rgb(100, 106, 115);"> 的 commit/tag 鎖定到同一大版本,避免 API 漂移帶來的兼容性問題。</font>

<font style="color:#3370FF;">3. </font>環境搭建(要點版)

3.1 連通性與健康檢查

| <font style="color:rgb(100, 106, 115);">Bash</font># 設備與狀態 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 <PEER-NPU-IP>; done | | :--- |

3.2 容器建議(示例)

使用 --privileged + --net=host,並掛載 Ascend 驅動/日誌路徑。

進入容器後,每次記得 source set_env.sh(toolkit 與 atb)。

3.3 安裝 CANN / torch / torch-npu

CANN:安裝 toolkit + kernels + nnal,磁盤預留 > 10GB;完成後:

<font style="color:rgb(100, 106, 115);">Bash</font>source /path/to/cann/ascend-toolkit/set_env.sh source /path/to/cann/nnal/atb/set_env.sh

PyTorch & torch-npu:固定源,避免“依賴衝突找不到包”的老問題:

<font style="color:rgb(100, 106, 115);">Bash</font>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 # 將自動裝 torch==2.5.1+cpu pip install torch-npu==2.5.1.post1.dev20250619

3.4 安裝 vLLM 與 vLLM-ascend

<font style="color:rgb(100, 106, 115);">Bash</font># 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 .
<font style="color:rgb(100, 106, 115);">克隆倉庫如遇到 SSL 校驗報錯,可臨時:</font><br/>

<font style="color:#3370FF;">4. </font>PD 分離部署流程

4.1 生成 ranktable.json

兩台參與 PD 的機器上執行(IP 順序:Prefill 在前,Decode 在後):

<font style="color:rgb(100, 106, 115);">Bash</font>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(Prefill 優先、Decode 其次)
--network-card-name:承載通信的網卡名(ifconfig 查同 IP)
--prefill/--decode-device-cnt:分配的 NPU 數量

4.2 Prefill 節點腳本(P)

<font style="color:rgb(100, 106, 115);">Bash</font># 環境與端口 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 # 拉起服務(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"}'
<font style="color:rgb(100, 106, 115);">關鍵項:--quantization ascend(w8a8 量化,避免 OOM)、--kv-transfer-config(PD 分離 KV 傳輸)。</font>

4.3 Decode 節點腳本(D)

<font style="color:rgb(100, 106, 115);">Bash</font># 環境與端口 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 # 拉起服務(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}}'
<font style="color:rgb(100, 106, 115);">Decode 端更關注 </font><font style="color:rgb(100, 106, 115);">RPS 與時延</font><font style="color:rgb(100, 106, 115);">,因此 max-model-len / max-num-batched-tokens 可按場景調小。</font>

4.4 分別拉起 P 與 D

<font style="color:rgb(100, 106, 115);">Bash</font># 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 機再開一個容器窗口,啓動 負載均衡代理

<font style="color:rgb(100, 106, 115);">Bash</font>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-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,輸出裏會顯示初始化成功的客户端數與服務地址。

<font style="color:#3370FF;">5. </font>功能驗證與壓測

5.1 API 驗證

<font style="color:rgb(100, 106, 115);">Bash</font>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 可查看更細日誌;響應中 choices[0].text 為模型輸出。

5.2 benchmark(vLLM 官方腳本)

<font style="color:rgb(100, 106, 115);">Bash</font>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
<font style="color:rgb(100, 106, 115);">關注指標:平均時延、P99、吞吐(req/s 或 tok/s)。對比 </font><font style="color:rgb(100, 106, 115);">PD 混部 vs PD 分離</font><font style="color:rgb(100, 106, 115);">,一般在中高併發下分離更穩。</font>

<font style="color:#3370FF;">6. </font>易錯點與快速修復

(1)torch-npu 找不到可用版本

現象:No matching distribution found for torch-npu

原因:源不對/被牆。

解法

<font style="color:rgb(100, 106, 115);">Bash</font>pip 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 torchvision==0.20.1 pip install torch-npu==2.5.1.post1.dev20250619

(2)依賴衝突:torch-npu 與 torch 版本不兼容

現象:Cannot install torch-npu==2.5.1.post1 and torch>=2.5.1 ...

解法

| <font style="color:rgb(100, 106, 115);">Bash</font>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 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 與實際卡數/網卡。

<font style="color:#3370FF;">7. </font>優化建議(進階)

KV 策略:長文本場景適當提高 --max-model-len,但要與 Decode 側併發上限平衡;觀察 PagedAttention 的 page 命中情況,避免頻繁遷移。

並行度:--tensor-parallel-size 與模型結構相關;EP(專家並行)建議先按官方實踐設置,壓測後再做微調。

IRQ/綁核:Decode 端對延遲敏感,建議業務線程與高頻 IRQ 分核(同 NUMA)。

代理層:把路由邏輯從業務進程剝離,便於後續橫向擴縮(多 P / 多 D)。

故障演練:壓測時主動製造 Decode 端抖動,觀察代理的重試/熔斷策略是否生效。

<font style="color:#3370FF;">8. </font>小結

PD 分離 讓 Prefill 的計算與 Decode 的訪存/帶寬壓力“各歸其位”,避免互相爭搶。

vLLM 的 PagedAttention 把 KV Cache 的佔用與碎片化壓得更穩,適合長上下文與高併發。

vLLM-ascend 上部署 DeepSeek-V3-w8a8 的關鍵,是 版本對齊量化生效HCCL 正確KV 傳輸配置

按文中流程走一遍,基本能做到“可復現、可壓測、可擴展”。剩下的,就是基於你的業務畫像做參數的工程化微調了。