人工智能大模型模型推理服务AscendCANN【免费下载链接】vllm-ascendCommunity maintained hardware plugin for vLLM on Huawei Ascend项目地址https://gitcode.com/gh_mirrors/vl/vllm-ascend点击查看免费下载导读本文档聚焦 vLLM-Ascend 在大规模Expert ParallelismEP专家并行场景下的分布式部署方案通过prefill-decodePD分离架构与分布式 DP Server让 Prefill 节点与 Decode 节点按各自负载特征采用差异化并行策略与优化配置从而更灵活地扩展 MoE 类大模型以 DeepSeek 为例的多节点推理集群。读完本文你将掌握多节点通信环境的物理层验证方法A2/A3 两代硬件命令差异、Prefiller 与 Decoder 两类节点的启动脚本与vllm serve参数配置、基于VLLM_DP_*环境变量的分布式 DP Server 拉起方式、负载均衡代理load_balance_proxy_server_example.py的用法以及基于 aisbench 的性能评测与 PD 场景调优参数。为什么需要分布式 DP ServerPD 分离 大规模 EP在 vLLM-Ascend 中Prefill预填充与 Decode解码阶段的计算特征截然不同Prefill 阶段以大量并行的 prompt 计算为主对吞吐与显存带宽敏感Decode 阶段则以低延迟、高并发的小 batch 推理为主。将两者部署在独立的节点组上即可针对各自特性分别实施优化策略实现更灵活的模型部署与更高的集群利用率。当 MoE 模型的专家并行规模EP扩大到跨多节点、甚至数十个 DP 引擎时单个vllm serve进程已难以承载全部并行组此时需要分布式 DP Server统一编排多个 DP 引擎的启动与通信。vLLM-Ascend 通过一组VLLM_DP_*环境变量将分布式 DP 所需的拓扑信息DP 总规模、master IP/端口、rank、本地规模等注入每个vllm serve进程从而把多节点上的多个推理引擎组织成一个逻辑上统一的 DP 集群。以 DeepSeek 模型为例官方文档给出了一个典型拓扑使用8 台 Atlas 800T A3 服务器IP 从192.0.0.1到192.0.0.8前 4 台作为 Prefiller 节点、后 4 台作为 Decoder 节点其中每个 Prefiller 节点独立充当自己的 master而 4 个 Decoder 节点统一以192.0.0.5作为 master。这一设计直接决定了后文脚本中dp_size_local与dp_rank_start的取值差异。第一步验证多节点通信环境大规模 EP 集群的通信依赖底层 NPU 互联。部署前必须逐节点完成物理层验证且结果必须全部为success、链路状态为UP。物理层要求所有物理机必须位于同一局域网内且网络互通所有 NPU 必须实现互联Atlas A2 代节点内通过HCCS互联节点间通过RDMA互联Atlas A3 代节点内与节点间均通过HCCS互联。A3 代验证流程A3 节点单机验证命令hccn_tool的 A3 变体# 检查远端交换机端口 for i in {0..15}; do hccn_tool -i $i -lldp -g | grep Ifname; done # 获取以太网口的链路状态UP 或 DOWN 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 # 查看网络探测到的 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 网络配置 cat /etc/hccn.conf获取 A3 NPU 的 IP 地址for i in {0..15}; do hccn_tool -i $i -vnic -g;done获取 superpodid 与 SDIDfor i in {0..15}; do npu-smi info -t spod-info -i $i -c 0;npu-smi info -t spod-info -i $i -c 1;done跨节点 PING 测试在目标节点上执行将x.x.x.x替换为实际的 NPU IP 地址for i in {0..15}; do hccn_tool -i $i -hccs_ping -g address x.x.x.x;doneA2 代验证流程A2 节点单机验证命令与 A3 的差异在于 NPU 编号范围为0..7且部分子命令不同# 检查远端交换机端口 for i in {0..7}; do hccn_tool -i $i -lldp -g | grep Ifname; done # 获取以太网口的链路状态UP 或 DOWN for i in {0..7}; do hccn_tool -i $i -link -g ; done # 检查网络健康状态 for i in {0..7}; do hccn_tool -i $i -net_health -g ; done # 查看网络探测到的 IP 配置 for i in {0..7}; do hccn_tool -i $i -netdetect -g ; done # 查看网关配置 for i in {0..7}; do hccn_tool -i $i -gateway -g ; done # 查看 NPU 网络配置 cat /etc/hccn.confA2 获取 NPU IP 地址使用-ip子命令A3 为-vnicfor i in {0..7}; do hccn_tool -i $i -ip -g;done跨节点 PING 测试A2 使用-pingA3 使用-hccs_ping# 在目标节点执行将 x.x.x.x 替换为实际 NPU IP 地址 for i in {0..7}; do hccn_tool -i $i -ping -g address x.x.x.x;done说明上述命令覆盖了 A2/A3 两代硬件的常用验证项具体可用子命令以实际 CANN 版本hccn_tool -h为准。第二步生成带配置的启动脚本run_dp_template.sh在 PD 分离场景下官方提供了一套经过优化的配置模板。以下 shell 脚本分别用于 Prefiller 节点与 Decoder 节点其核心思路是从分布式 DP Server 接收一组位置参数$1~$7转换为VLLM_DP_*环境变量再启动vllm serve。Prefiller 节点模板# run_dp_template.sh #!/bin/sh # 通过 ifconfig 获取 # nic_name 是对应 local_ip 的网络接口名 nic_namexxxx local_ipxxxx # HCCL 与连接的基础配置 export HCCL_IF_IP$local_ip export GLOO_SOCKET_IFNAME$nic_name export TP_SOCKET_IFNAME$nic_name export HCCL_SOCKET_IFNAME$nic_name export OMP_PROC_BINDfalse export OMP_NUM_THREADS10 export HCCL_BUFFSIZE256 # 从分布式 DP Server 获取参数 export VLLM_DP_SIZE$1 export VLLM_DP_MASTER_IP$2 export VLLM_DP_MASTER_PORT$3 export VLLM_DP_RANK_LOCAL$4 export VLLM_DP_RANK$5 export VLLM_DP_SIZE_LOCAL$7 # pytorch_npu 与 vllm 设置 export PYTORCH_NPU_ALLOC_CONFexpandable_segments:True export TASK_QUEUE_ENABLE1 export VLLM_USE_MODELSCOPETrue # 启用分布式 DP Server export VLLM_WORKER_MULTIPROC_METHODfork export VLLM_ASCEND_EXTERNAL_DP_LB_ENABLED1 # W8A8 权重可从 ModelScope 获取vllm-ascend/DeepSeek-R1-W8A8 # --additional-config 用于开启 vllm-ascend 特性 vllm serve vllm-ascend/DeepSeek-R1-W8A8 \ --host 0.0.0.0 \ --port $6 \ --tensor-parallel-size 8 \ --enable-expert-parallel \ --seed 1024 \ --served-model-name deepseek_r1 \ --max-model-len 17000 \ --max-num-batched-tokens 16384 \ --trust-remote-code \ --max-num-seqs 4 \ --gpu-memory-utilization 0.9 \ --quantization ascend \ --speculative-config {num_speculative_tokens: 1, method:deepseek_mtp} \ --enforce-eager \ --kv-transfer-config \ {kv_connector: MooncakeConnectorV1, kv_buffer_device: npu, kv_role: kv_producer, kv_parallel_size: 1, kv_port: 20001 } \ --additional-config {enable_weight_nz_layout:true,enable_prefill_optimizations:true}Decoder 节点模板# run_dp_template.sh #!/bin/sh nic_namexxxx local_ipxxxx # HCCL 与连接的基础配置 export HCCL_IF_IP$local_ip export GLOO_SOCKET_IFNAME$nic_name export TP_SOCKET_IFNAME$nic_name export HCCL_SOCKET_IFNAME$nic_name export OMP_PROC_BINDfalse export OMP_NUM_THREADS10 export HCCL_BUFFSIZE1024 # 从分布式 DP Server 获取参数 export VLLM_DP_SIZE$1 export VLLM_DP_MASTER_IP$2 export VLLM_DP_MASTER_PORT$3 export VLLM_DP_RANK_LOCAL$4 export VLLM_DP_RANK$5 export VLLM_DP_SIZE_LOCAL$7 # pytorch_npu 与 vllm 设置 export PYTORCH_NPU_ALLOC_CONFexpandable_segments:True export TASK_QUEUE_ENABLE1 export VLLM_USE_MODELSCOPETrue # 启用分布式 DP Server export VLLM_WORKER_MULTIPROC_METHODfork export VLLM_ASCEND_EXTERNAL_DP_LB_ENABLED1 vllm serve vllm-ascend/DeepSeek-R1-W8A8 \ --host 0.0.0.0 \ --port $6 \ --tensor-parallel-size 1 \ --enable-expert-parallel \ --seed 1024 \ --served-model-name deepseek_r1 \ --max-model-len 17000 \ --max-num-batched-tokens 256 \ --trust-remote-code \ --max-num-seqs 28 \ --gpu-memory-utilization 0.9 \ --quantization ascend \ --speculative-config {num_speculative_tokens: 1, method:deepseek_mtp} \ --kv-transfer-config \ {kv_connector: MooncakeConnectorV1, kv_buffer_device: npu, kv_role: kv_consumer, kv_parallel_size: 1, kv_port: 20001 } \ --additional-config {enable_weight_nz_layout:true}模板脚本中的关键点脚本位置参数由分布式 DP Server 传入$1DP 总规模$2DP master IP$3DP master 端口$4本地 rank$5全局 rank$6本引擎的 serve 端口$7本地 DP 规模Prefiller 与 Decoder 的关键差异Prefiller 设置HCCL_BUFFSIZE256、--tensor-parallel-size 8、--max-num-batched-tokens 16384、--max-num-seqs 4并追加--enforce-eagerDecoder 设置HCCL_BUFFSIZE1024、--tensor-parallel-size 1、--max-num-batched-tokens 256、--max-num-seqs 28KV 传输角色Prefiller 为kv_role: kv_producer生产 KVDecoder 为kv_role: kv_consumer消费 KV二者通过MooncakeConnectorV1连接器在kv_port: 20001上交互--enable-expert-parallel开启专家并行。vLLM-Ascend 的并行配置补丁patch_parallel_config.py会进一步影响 MoE 序列并行的启用逻辑说明 EP 在 Ascend 上与其他并行度TP/DP是协同生效的--quantization ascend启用 Ascend 侧量化此处为 W8A8配合--additional-config中的enable_weight_nz_layout将量化权重转换为 NZ 格式以加速矩阵乘。第三步在所有节点启动分布式 DP Server将上一步的模板脚本与下面的 Python 启动文件放在同一目录然后在所有节点分别执行官方建议在v0.9.1 正式版本上使用该特性。启动文件的核心逻辑是按dp_size_local创建多个multiprocessing.Process每个进程以bash ./run_dp_template.sh dp_size dp_ip dp_port dp_rank_local dp_rank engine_port dp_size_local的形式拉起一个推理引擎。Prefiller 节点启动文件import multiprocessing import os import sys dp_size 2 # 当前 DP 组的引擎总数decode/prefill dp_size_local 2 # 当前节点上的 DP 引擎数 dp_rank_start 0 # 当前节点的起始 DP rank # 在本示例中每个 prefiller 节点的 dp_ip 各不相同 dp_ip 192.0.0.1 # DP 通信的 master 节点 IP dp_port 13395 # DP 通信使用的端口 engine_port 9000 # 当前节点所有 DP 组的起始端口 template_path ./run_dp_template.sh if not os.path.exists(template_path): print(fTemplate file {template_path} does not exist.) sys.exit(1) def run_command(dp_rank_local, dp_rank, engine_port_): command fbash ./run_dp_template.sh {dp_size} {dp_ip} {dp_port} {dp_rank_local} {dp_rank} {engine_port_} {dp_size_local} os.system(command) processes [] for i in range(dp_size_local): dp_rank dp_rank_start i dp_rank_local i engine_port_ engine_port i process multiprocessing.Process(targetrun_command, args(dp_rank_local, dp_rank, engine_port_)) processes.append(process) process.start() for process in processes: process.join()Decoder 节点启动文件import multiprocessing import os import sys dp_size 64 # 当前 DP 组的引擎总数decode/prefill dp_size_local 16 # 当前节点上的 DP 引擎数 dp_rank_start 0 # 当前节点的起始 DP rank例如 0/16/32/48 # 在本示例中所有 decoder 节点的 dp_ip 相同 dp_ip 192.0.0.5 # DP 通信的 master 节点 IP dp_port 13395 # DP 通信使用的端口 engine_port 9000 # 当前节点所有 DP 组的起始端口 template_path ./run_dp_template.sh if not os.path.exists(template_path): print(fTemplate file {template_path} does not exist.) sys.exit(1) def run_command(dp_rank_local, dp_rank, engine_port_): command fbash ./run_dp_template.sh {dp_size} {dp_ip} {dp_port} {dp_rank_local} {dp_rank} {engine_port_} {dp_size_local} os.system(command) processes [] for i in range(dp_size_local): dp_rank dp_rank_start i dp_rank_local i engine_port_ engine_port i process multiprocessing.Process(targetrun_command, args(dp_rank_local, dp_rank, engine_port_)) processes.append(process) process.start() for process in processes: process.join()两类节点的差异说明注意Prefiller 节点与 Decoder 节点的配置可以不同。在本示例中每个 Prefiller 节点独立作为 master因此各节点的dp_ip是自身 IPdp_rank_start均为 0而Decoder 节点统一以192.0.0.5作为 master因此 4 个节点的dp_rank_start分别取0/16/32/48。这直接导致两类节点在dp_size_local与dp_rank_start上的取值差异。第四步启动负载均衡代理示例PD 分离场景下需要一层代理来将请求分发到 Prefiller 与 Decoder 后端。仓库提供了示例代理程序 load_balance_proxy_server_example.py它基于 FastAPI httpx 实现支持 OpenAI 兼容的/v1/completions与/v1/chat/completions接口、SSE 流式响应、按负载优先级的调度最小堆以及后端实例的动态增删。按 8 节点示例4 Prefiller 4 Decoder每个 Prefiller 节点 2 个引擎、每个 Decoder 节点 16 个引擎启动代理python load_balance_proxy_server_example.py \ --port 8000 \ --host 0.0.0.0 \ --prefiller-hosts \ 192.0.0.1 \ 192.0.0.2 \ 192.0.0.3 \ 192.0.0.4 \ --prefiller-hosts-num \ 2 2 2 2 \ --prefiller-ports \ 9000 9000 9000 9000 \ --prefiller-ports-inc \ 2 2 2 2\ --decoder-hosts \ 192.0.0.5 \ 192.0.0.6 \ 192.0.0.7 \ 192.0.0.8 \ --decoder-hosts-num \ 16 16 16 16 \ --decoder-ports \ 9000 9000 9000 9000 \ --decoder-ports-inc \ 16 16 16 16代理参数说明参数含义--port代理服务端口--host代理服务主机 IP--prefiller-hostsPrefiller 节点主机列表--prefiller-hosts-numPrefiller 节点主机的重复次数--prefiller-portsPrefiller 节点端口--prefiller-ports-incPrefiller 节点端口的递增步长--decoder-hostsDecoder 节点主机列表--decoder-hosts-numDecoder 节点主机的重复次数--decoder-portsDecoder 节点端口--decoder-ports-incDecoder 节点端口的递增步长结合代理源码load_balance_proxy_server_example.py可进一步理解其工作原理调度状态共享SharedProxyScheduler以RolePools分别维护 Prefill/Decode 两个角色池使用“惰性删除最小堆”lazy-deletion min-heap做负载优先级调度Prefill 侧的优先级为active_tokens active_kv_cache * 0.3Decode 侧为active_tokens实现基于活跃 token 与 KV 压力的负载均衡PD 协作流程请求先被发送到某个 Prefiller 完成预填充build_prefill_request会注入kv_transfer_params并设置max_tokens1触发远程解码随后按kv_transfer_params选择 Decoder 消费 KV 并流式返回生成结果动态扩缩容代理暴露POST /instances/add与POST /instances/remove接口新增实例会先进入waiting_nodes由NodeListener轮询/models健康检查确认就绪后再激活删除实例则采用“taint隔离”机制等待在途请求排空后移除健康检查GET /healthcheck返回代理状态、Prefiller/Decoder 实例数及累计请求数。该代理其余参数如--max-retries、--retry-delay、--max-waiting-retries、--waiting-retry-interval、--workers、--log-level均可在源码的parse_args()中查看load_balance_proxy_server_example.py 中--port默认 8000、--host默认 localhost、--workers默认 1。第五步使用 aisbench 进行性能评测官方推荐使用aisbench工具评估性能。安装方式git clone https://github.com/AISBench/benchmark.git cd benchmark/ pip3 install -e ./评测前需取消 http 代理# 取消代理 unset http_proxy unset https_proxy使用要点数据集可放在benchmark/ais_bench/datasets目录可在benchmark/ais_bench/benchmark/configs/models/vllm_api目录修改配置以vllm_api_stream_chat.py为例models [ dict( attrservice, typeVLLMCustomAPIChatStream, abbrvllm-api-stream-chat, pathvllm-ascend/DeepSeek-R1-W8A8, modeldsr1, request_rate 28, retry 2, host_ip 192.0.0.1, # 代理服务主机 IP host_port 8000, # 代理服务端口 max_out_len 10, batch_size1536, trust_remote_codeTrue, generation_kwargs dict( temperature 0, seed 1024, ignore_eosFalse, ) ) ]其中host_ip/host_port指向负载均衡代理而非具体后端引擎batch_size与request_rate决定了压测强度。以 gsm8k 数据集为例执行评测ais_bench --models vllm_api_stream_chat --datasets gsm8k_gen_0_shot_cot_str_perf --debug --mode perfaisbench 的命令与参数详情以其官方文档为准。Prefill 与 Decode 配置细节PD 分离场景下官方提供了一套优化配置两类节点的关键差异如下。Prefiller 节点设置HCCL_BUFFSIZE256在vllm serve命令中追加--enforce-eager跳过图模式编译减少 Prefill 节点的启动/编译开销--kv-transfer-config采用如下配置角色为kv_producer--kv-transfer-config \ {kv_connector: MooncakeConnectorV1, kv_buffer_device: npu, kv_role: kv_producer, kv_parallel_size: 1, kv_port: 20001 }--additional-config采用如下配置--additional-config {enable_weight_nz_layout:true,enable_prefill_optimizations:true}Decoder 节点设置HCCL_BUFFSIZE1024--kv-transfer-config采用如下配置角色为kv_consumer--kv-transfer-config {kv_connector: MooncakeConnectorV1, kv_buffer_device: npu, kv_role: kv_consumer, kv_parallel_size: 1, kv_port: 20001 }--additional-config采用如下配置--additional-config {enable_weight_nz_layout:true}参数说明--additional-config参数含义enable_weight_nz_layout是否将量化权重转换为 NZ 格式以加速矩阵乘法。对应到源码层面vLLM-Ascend 的 AscendConfig 提供了weight_nz_mode字段ascend_config.py其取值约束为0/1/2非法值会抛出ValueError默认值为1说明 NZ 布局转换是 Ascend 上量化推理的默认路径enable_prefill_optimizations是否启用 DeepSeek 系列模型的 Prefill 阶段优化。启用 MTPMulti-Token Prediction在配置中加入以下命令即可启用单 token 步进的 MTP 投机解码--speculative-config {num_speculative_tokens: 1, method:deepseek_mtp}推荐配置示例假设输入平均长度 3.5k、输出长度 1.1k、上下文长度 16k、输入数据集最大长度 7k采用 4 个节点做 Prefill、4 个节点做 Decode 时官方给出的分布式 DP Server 大规模 EP 推荐配置如下节点DPTPEPmax-model-lenmax-num-batched-tokensmax-num-seqsgpu-memory-utilizationprefill2816170001638440.9decode6416417000256280.9注意这些配置并非自动优化结果需要根据实际场景调整。表格中 Prefill 节点 DP2、TP8、EP16意味着每个 Prefill 节点内部同时运行 2 个 DP 引擎对应启动文件dp_size_local2每个引擎 TP8、EP 规模为 16Decode 节点 DP644 节点 × 每节点 16 个引擎、TP1、EP64符合“Decode 端更扁平、并行度更高”的 PD 分离设计意图。FAQPrefiller 节点需要预热由于部分 NPU 算子的计算需要经过数轮预热才能达到最佳性能官方建议在进行性能测试前先用少量请求预热服务以获得最佳的端到端吞吐。这与 vLLM-Ascend 提供的预热配置如ascend_warmup_config.enable_early_kernel_warmup、enable_early_nz_warmup见 ascend_config.py相互印证在 PD 分离的大规模 EP 集群中对 Prefiller 与 Decoder 分别做预热能显著影响压测结果的真实性。总结本文完整梳理了 vLLM-Ascend 大规模 EP 场景下的分布式 DP Server 部署链路从 A2/A3 多节点通信环境验证到 Prefiller/Decoder 差异化启动脚本与VLLM_DP_*环境变量的传递再到负载均衡代理与 aisbench 评测以及--additional-config、--kv-transfer-config、MTP 投机解码等关键参数。结合仓库中的示例load_balance_proxy_server_example.py、run_dp_template.sh、launch_online_dp.py与配置解析源码ascend_config.py、patch_parallel_config.py你可以据此搭建、调优并评测自己的 PD 分离大规模 EP 推理集群。赞分享人工智能大模型模型推理服务AscendCANN【免费下载链接】vllm-ascendCommunity maintained hardware plugin for vLLM on Huawei Ascend项目地址https://gitcode.com/gh_mirrors/vl/vllm-ascend点击查看免费下载相关推荐vllm-ascend 基于 MooncakeConnectorV1 的 PD 分离部署指南prefill/decode 双节点配置与负载均衡代理vllm ascend 基于 MooncakeConnectorV1 的 PD 分离部署指南prefill/decode 双节点配置与负载均衡代理 本指南完整人工智能大模型模型推理服务AscendCANN如何实现segmentation_models.pytorch分布式推理多节点部署与负载均衡完整指南如何实现segmentation_models.pytorch分布式推理多节点部署与负载均衡完整指南 segmentation_models.pytorch是人工智能深度学习计算机视觉vLLM Ascend DyntraLB 实践指南P/D 分离 Decode 端的 DP 数据并行负载均衡调度vLLM Ascend DyntraLB 实践指南P/D 分离 Decode 端的 DP 数据并行负载均衡调度 DyntraLB 是 vllm ascend人工智能大模型模型推理服务AscendCANN创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考