预填充-解码分离架构的 Llmdatadist 验证(Qwen)#

开始之前#

vLLM-Ascend 现已支持预填充-解码分离架构,并包含专家并行的选项。本指南将引导您在受限的资源环境下,一步步验证这些功能。

以 Qwen3-30B-A3B 模型为例,在 3 台 Atlas 800T A2 服务器上使用 vllm-ascend v0.10.1rc1 (附带 vLLM v0.10.1.1) 来部署 "1P2D" 架构。假设预填充服务器的 IP 地址为 192.0.0.1,解码服务器分别为 192.0.0.2 (解码器 1) 和 192.0.0.3 (解码器 2)。每台服务器使用 2 个 NPU 来部署一个服务实例。

验证多节点通信环境#

物理层要求#

  • 物理服务器必须位于同一局域网内,并确保网络互通。

  • 所有 NPU 必须能够互联。节点内通过 HCCS 互联,节点间通过 RDMA 互联。

验证流程#

  1. 单节点验证:

请依次在每个节点上执行以下命令。所有结果必须为 success,状态必须为 UP

# Check the remote switch ports
for i in {0..7}; do hccn_tool -i $i -lldp -g | grep Ifname; done
# Get the link status of the Ethernet ports (UP or DOWN)
for i in {0..7}; do hccn_tool -i $i -link -g ; done
# Check the network health status
for i in {0..7}; do hccn_tool -i $i -net_health -g ; done
# View the network detected IP configuration
for i in {0..7}; do hccn_tool -i $i -netdetect -g ; done
# View gateway configuration
for i in {0..7}; do hccn_tool -i $i -gateway -g ; done
# View NPU network configuration
cat /etc/hccn.conf
  1. 获取 NPU IP 地址

for i in {0..7}; do hccn_tool -i $i -ip -g;done
  1. 跨节点 PING 测试

# Execute on the target node (replace 'x.x.x.x' with actual npu ip address)
for i in {0..7}; do hccn_tool -i $i -ping -g address x.x.x.x;done

生成 Ranktable (排序表)#

Ranktable 是一个 JSON 文件,用于指定昇腾 NPU 的等级到节点的映射关系。更多详情,请参考 vllm-ascend 示例。请执行以下命令作为参考。

cd vllm-ascend/examples/disaggregate_prefill_v1/
bash gen_ranktable.sh --ips <prefiller_node1_local_ip> <prefiller_node2_local_ip> <decoder_node1_local_ip> <decoder_node2_local_ip> \
  --npus-per-node  <npu_clips> --network-card-name <nic_name> --prefill-device-cnt <prefiller_npu_clips> --decode-device-cnt <decode_npu_clips> \
  [--local-device-ids <id_1>,<id_2>,<id_3>...]

假设我们在预填充服务器节点上使用设备 0 和 1,在两个解码服务器节点上均使用设备 6 和 7。以下命令仅供参考。(如果您需要在本地服务器上指定特定的 NPU 设备,则 --local-device-ids 参数是必需的。)

# On the prefiller node
cd vllm-ascend/examples/disaggregate_prefill_v1/
bash gen_ranktable.sh --ips 192.0.0.1 192.0.0.2 192.0.0.3 \
  --npus-per-node  2 --network-card-name eth0 --prefill-device-cnt 2 --decode-device-cnt 4 --local-device-ids 0,1

# On the decoder 1
cd vllm-ascend/examples/disaggregate_prefill_v1/
bash gen_ranktable.sh --ips 192.0.0.1 192.0.0.2 192.0.0.3 \
  --npus-per-node  2 --network-card-name eth0 --prefill-device-cnt 2 --decode-device-cnt 4 --local-device-ids 6,7

# On the decoder 2
cd vllm-ascend/examples/disaggregate_prefill_v1/
bash gen_ranktable.sh --ips 192.0.0.1 192.0.0.2 192.0.0.3 \
  --npus-per-node  2 --network-card-name eth0 --prefill-device-cnt 2 --decode-device-cnt 4 --local-device-ids 6,7

Ranktable 将生成在 /vllm-workspace/vllm-ascend/examples/disaggregate_prefill_v1/ranktable.json 路径下

参数

含义

--ips

每个节点的本地 IP 地址(预填充节点应排在解码节点之前)

--npus-per-node

每个节点的 NPU 数量

--network-card-name

物理服务器的网卡名称

--prefill-device-cnt

用于预填充的 NPU 数量

--decode-device-cnt

用于解码的 NPU 数量

--local-device-ids

可选。如果使用本地节点的所有设备,则无需指定。

预填充器/解码器部署#

我们可以分别运行以下脚本来在预填充器/解码器节点上启动服务器。

export HCCL_IF_IP=192.0.0.1 # node ip
export GLOO_SOCKET_IFNAME="eth0"  # network card name
export TP_SOCKET_IFNAME="eth0"
export HCCL_SOCKET_IFNAME="eth0"
export DISAGGREGATED_PREFILL_RANK_TABLE_PATH="/path/to/your/generated/ranktable.json"
export OMP_PROC_BIND=false
export OMP_NUM_THREADS=10
export VLLM_USE_V1=1

vllm serve /model/Qwen3-30B-A3B  \
  --host 0.0.0.0 \
  --port 13700 \
  --tensor-parallel-size 2 \
  --no-enable-prefix-caching \
  --seed 1024 \
  --served-model-name qwen3-moe \
  --max-model-len 6144  \
  --max-num-batched-tokens 6144  \
  --trust-remote-code \
  --gpu-memory-utilization 0.9  \
  --enable-expert-parallel \
  --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"
  }'  \
  --additional-config \
  '{"torchair_graph_config": {"enabled":false,              "enable_multistream_shared_expert":false}, "ascend_scheduler_config":{"enabled":true, "enable_chunked_prefill":false}}' \
  --enforce-eager
export HCCL_IF_IP=192.0.0.2  # node ip
export GLOO_SOCKET_IFNAME="eth0"  # network card name
export TP_SOCKET_IFNAME="eth0"
export HCCL_SOCKET_IFNAME="eth0"
export DISAGGREGATED_PREFILL_RANK_TABLE_PATH="/path/to/your/generated/ranktable.json"
export OMP_PROC_BIND=false
export OMP_NUM_THREADS=10
export VLLM_USE_V1=1

vllm serve /model/Qwen3-30B-A3B  \
  --host 0.0.0.0 \
  --port 13700 \
  --no-enable-prefix-caching \
  --tensor-parallel-size 2 \
  --seed 1024 \
  --served-model-name qwen3-moe \
  --max-model-len 6144  \
  --max-num-batched-tokens 6144  \
  --trust-remote-code \
  --gpu-memory-utilization 0.9  \
  --enable-expert-parallel \
  --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":false, "enable_multistream_shared_expert":false}, "ascend_scheduler_config":{"enabled":true, "enable_chunked_prefill":false}}'
export HCCL_IF_IP=192.0.0.3  # node ip
export GLOO_SOCKET_IFNAME="eth0"  # network card name
export TP_SOCKET_IFNAME="eth0"
export HCCL_SOCKET_IFNAME="eth0"
export DISAGGREGATED_PREFILL_RANK_TABLE_PATH="/path/to/your/generated/ranktable.json"
export OMP_PROC_BIND=false
export OMP_NUM_THREADS=10
export VLLM_USE_V1=1

vllm serve /model/Qwen3-30B-A3B  \
  --host 0.0.0.0 \
  --port 13700 \
  --no-enable-prefix-caching \
  --tensor-parallel-size 2 \
  --seed 1024 \
  --served-model-name qwen3-moe \
  --max-model-len 6144  \
  --max-num-batched-tokens 6144  \
  --trust-remote-code \
  --gpu-memory-utilization 0.9  \
  --enable-expert-parallel \
  --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":false, "enable_multistream_shared_expert":false}, "ascend_scheduler_config":{"enabled":true, "enable_chunked_prefill":false}}'

用于部署的示例代理#

在与预填充服务实例相同的节点上运行一个代理服务器。您可以在代码库的示例中获取该代理程序:load_balance_proxy_server_example.py

python load_balance_proxy_server_example.py \
    --host 192.0.0.1 \
    --port 8080 \
    --prefiller-hosts 192.0.0.1 \
    --prefiller-port 13700 \
    --decoder-hosts 192.0.0.2 192.0.0.3 \
    --decoder-ports 13700 13700

验证#

使用代理服务器的端点来检查服务健康状态。

curl http://192.0.0.1:8080/v1/completions \
    -H "Content-Type: application/json" \
    -d '{
        "model": "qwen3-moe",
        "prompt": "Who are you?",
        "max_tokens": 100,
        "temperature": 0
    }'