Qwen3.5-397B-A17B¶
1 简介¶
Qwen3.5-397B-A17B 是一个大规模 Qwen3.5 MoE 模型,结合多模态能力、长上下文推理、MTP 推测解码以及 W8A8 量化部署,用于在 Ascend 硬件上进行生产级服务。
本文档介绍该模型的主要验证步骤,包括支持的功能、前提条件、安装、单节点在线部署、多节点部署、Prefill-Decode(PD)分离、功能验证、精度与性能评估、性能调优以及常见问题。
Qwen3.5-397B-A17B 模型首次支持于 vllm-ascend:v0.17.0rc1。使用该模型时请使用 v0.17.0rc1 或更高版本。对于 Ascend95DT,该模型从 vllm-ascend:v0.23.0rc1 开始支持。以下示例使用文档构建系统配置的版本占位符。
2 支持的功能¶
参见支持的功能以获取该模型支持的功能矩阵,包括 BF16、W8A8 量化、分块预填充、自动前缀缓存、推测解码、异步调度、张量并行、专家并行、数据并行、PD 分离和 ACLGraph 支持。
参见功能指南以获取功能配置详情。
:::{note}
支持矩阵记录的是该模型已验证的最大能力。本文档中的启动示例采用面向在线服务和性能测试的实用验证配置。请根据服务负载和可用 KV 缓存调整 --max-model-len、--max-num-seqs 和 --max-num-batched-tokens。
:::
3 前提条件¶
3.1 模型权重¶
| 权重版本 | 硬件要求 | 下载链接 |
|---|---|---|
Qwen3.5-397B-A17B(BF16 版本) |
2 个 950DT Products(96GB x 8)节点或 2 个 Atlas 800 A3(64GB x 16)节点或 4 个 Atlas 800 A2(64GB x 8)节点 | ModelScope |
Qwen3.5-397B-A17B-w8a8(量化版本) |
1 个 Atlas 800 A3(64GB x 16)节点或 2 个 Atlas 800 A2(64GB x 8)节点 | ModelScope |
Qwen3.5-397B-A17B-w4a8(量化版本) |
1 个 Atlas 800 A3(64GB x 16)节点或 2 个 Atlas 800 A2(64GB x 8)节点 | ModelScope |
Qwen3.5-397B-A17B-w8a8-mxfp8(量化版本) |
1 个 950DT Products(96GB x 8)节点 | ModelScope |
Qwen3.5-397B-A17B-w4a4-mxfp4(量化版本) |
1 个 950DT Products(96GB x 8)节点 | ModelScope |
建议将模型权重下载到多节点共享目录中,例如 /root/.cache/,以便所有服务节点加载相同路径。
路径说明:将模型权重下载到您选择的目录并记录该目录。确保后续部署命令中的模型路径与该目录一致。
3.2 验证多节点通信(可选)¶
如果要在多节点环境中部署该模型,请按照验证多节点通信环境验证通信环境。
4 安装¶
4.1 Docker 镜像安装¶
请根据机器类型选择镜像,并在节点上启动 Docker 镜像,参见使用 Docker。
Qwen3.5-397B-A17B 模型首次支持于 vllm-ascend:v0.17.0rc1。使用该模型时请使用 v0.17.0rc1 或更高版本。对于 Ascend95DT,该模型从 vllm-ascend:v0.23.0rc1 开始支持。
在每个节点上启动 Docker 镜像。
export IMAGE=quay.io/ascend/vllm-ascend:v0.23.0-a5
export NAME=vllm-ascend
docker run --rm \
--name $NAME \
--net=host \
--shm-size=1g \
--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/davinci_manager \
--device /dev/hisi_hdc \
--device /dev/ummu \
--device /dev/uburma \
-v /usr/local/Ascend/driver:/usr/local/Ascend/driver \
-v /etc/ascend_install.info:/etc/ascend_install.info \
-v /etc/hccl_rootinfo.json:/etc/hccl_rootinfo.json \
-v /etc/hixlep/:/etc/hixlep/ \
-v /root/.cache:/root/.cache \
-v /usr/local/sbin:/usr/local/sbin \
-v /usr/local/dcmi:/usr/local/dcmi \
-v /usr/local/bin/npu-smi:/usr/local/bin/npu-smi \
-v /usr/local/sbin/npu-smi:/usr/local/sbin/npu-smi \
-v /usr/lib64:/usr/lib64 \
-itd $IMAGE bash
在每个节点上启动 Docker 镜像。
export IMAGE=quay.io/ascend/vllm-ascend:v0.23.0-a3
export NAME=vllm-ascend
docker run --rm \
--name $NAME \
--net=host \
--shm-size=1g \
--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 \
--device /dev/davinci_manager \
--device /dev/devmm_svm \
--device /dev/hisi_hdc \
-v /usr/local/dcmi:/usr/local/dcmi \
-v /usr/local/Ascend/driver/tools/hccn_tool:/usr/local/Ascend/driver/tools/hccn_tool \
-v /usr/local/bin/npu-smi:/usr/local/bin/npu-smi \
-v /usr/local/Ascend/driver/lib64/:/usr/local/Ascend/driver/lib64/ \
-v /usr/local/Ascend/driver/version.info:/usr/local/Ascend/driver/version.info \
-v /etc/ascend_install.info:/etc/ascend_install.info \
-v /root/.cache:/root/.cache \
-it $IMAGE bash
请在每个节点上启动 Docker 镜像。
export IMAGE=quay.io/ascend/vllm-ascend:v0.23.0
export NAME=vllm-ascend
docker run --rm \
--name $NAME \
--net=host \
--shm-size=1g \
--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/davinci_manager \
--device /dev/devmm_svm \
--device /dev/hisi_hdc \
-v /usr/local/dcmi:/usr/local/dcmi \
-v /usr/local/Ascend/driver/tools/hccn_tool:/usr/local/Ascend/driver/tools/hccn_tool \
-v /usr/local/bin/npu-smi:/usr/local/bin/npu-smi \
-v /usr/local/Ascend/driver/lib64/:/usr/local/Ascend/driver/lib64/ \
-v /usr/local/Ascend/driver/version.info:/usr/local/Ascend/driver/version.info \
-v /etc/ascend_install.info:/etc/ascend_install.info \
-v /root/.cache:/root/.cache \
-it $IMAGE bash
进入容器后,验证 vLLM 和 vLLM-Ascend 是否可以导入:
如果要部署多节点服务,请在每个节点上配置相同的环境。
4.2 源代码安装¶
您也可以从源代码构建并安装 vllm-ascend。请参考 使用 Python 设置。
如果要部署多节点服务,请在每个节点上安装相同版本的 vLLM 和 vLLM-Ascend。
5 在线服务部署¶
5.1 单节点在线部署¶
单节点部署在同一节点上同时运行 Prefill 和 Decode。它适用于功能验证和长上下文单集群服务。
运行以下脚本,在 1 台 950DT 产品(96G x 8)上执行在线推理。量化版本(Qwen3.5-397B-A17B-w8a8-mxfp8 和 Qwen3.5-397B-A17B-w4a4-mxfp4)可以部署在单个 950DT 产品节点上,需要 --quantization ascend。
#!/bin/sh
# Load model from ModelScope to speed up download.
export VLLM_USE_MODELSCOPE=True
export HCCL_BUFFSIZE=400
export HCCL_INTRA_ROCE_ENABLE=0
export HCCL_OP_EXPANSION_MODE="AIV"
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export VLLM_ASCEND_ENABLE_PREFETCH_MLP=1
# Reduce memory fragmentation and avoid out-of-memory errors.
# Ensure the model path matches the directory recorded during download
vllm serve Eco-Tech/Qwen3.5-397B-A17B-w4a4-mxfp4 \
--host 0.0.0.0 \
--port 8000 \
--distributed-executor-backend mp \
--data-parallel-size 1 \
--tensor-parallel-size 8 \
--enable-expert-parallel \
--seed 1024 \
--quantization ascend \
--served-model-name qwen3.5 \
--max-num-seqs 128 \
--max-model-len 133000 \
--max-num-batched-tokens 8192 \
--trust-remote-code \
--enable-prefix-caching \
--gpu-memory-utilization 0.95 \
--async-scheduling \
--speculative-config '{"method": "qwen3_5_mtp", "num_speculative_tokens": 3}' \
--compilation-config '{"cudagraph_mode":"FULL_DECODE_ONLY"}' \
--additional-config '{"enable_cpu_binding":true}'
运行以下脚本,在 1 台 Atlas 800 A3(64GB x 16)上执行 128k 在线推理,并在 1 台 Atlas 800 A3(64GB x 16)节点上进行 W8A8 部署。W8A8 版本需要 --quantization ascend。
#!/bin/sh
# Load model from ModelScope to speed up download.
export VLLM_USE_MODELSCOPE=True
export HCCL_BUFFSIZE=1024
export HCCL_OP_EXPANSION_MODE="AIV"
export LD_PRELOAD=/usr/lib/aarch64-linux-gnu/libjemalloc.so.2:$LD_PRELOAD
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
# Reduce memory fragmentation and avoid out-of-memory errors.
echo performance | tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
sysctl -w vm.swappiness=0
sysctl -w kernel.numa_balancing=0
sysctl kernel.sched_migration_cost_ns=50000
# Ensure the model path matches the directory recorded during download
vllm serve Eco-Tech/Qwen3.5-397B-A17B-w8a8-mtp \
--host 0.0.0.0 \
--port 8000 \
--data-parallel-size 1 \
--tensor-parallel-size 16 \
--enable-expert-parallel \
--seed 1024 \
--quantization ascend \
--served-model-name qwen3.5 \
--max-num-seqs 128 \
--max-model-len 133000 \
--max-num-batched-tokens 16384 \
--trust-remote-code \
--gpu-memory-utilization 0.90 \
--enable-prefix-caching \
--speculative-config '{"method": "qwen3_5_mtp", "num_speculative_tokens": 3, "enforce_eager": true}' \
--compilation-config '{"cudagraph_mode":"FULL_DECODE_ONLY"}' \
--additional-config '{"enable_cpu_binding":true, "enable_fused_mc2":1}'
对于 W8A8 部署,需要 2 台 Atlas 800 A2(64G x 8)节点。多节点 MP 部署请参考 第 5.2 节。
常见问题提示:如果服务启动失败、HBM 不足,或请求未按预期调度,请先参考 公共常见问题,然后查看第 10 节中的模型特定常见问题。
关键参数:
--data-parallel-size 1和--tensor-parallel-size 16为一台 16-NPU A3 节点设置 DP 和 TP。--enable-expert-parallel为 MoE 层启用专家并行。请勿在同一 MoE 层中混用 MoE 张量并行和专家并行。--max-model-len是单个请求的最大输入加输出长度。仅在 KV 缓存充足时才增大该值。--max-num-seqs是每个 DP 组调度的最大活动请求数。进行性能测试时,请将--max-num-seqs * --data-parallel-size设置为大于或等于测试并发数。--max-num-batched-tokens是单个调度步骤中处理的最大 token 数。较大的值可以提高 prefill 效率,但会消耗更多激活内存。--gpu-memory-utilization控制 vLLM 可用于计算 KV 缓存容量的 HBM 比例。较高的值会增大 KV 缓存大小,但如果运行时内存高于 profiling 阶段测得的内存,可能触发 OOM。--enable-prefix-caching启用前缀缓存。对于 Qwen3.5,当混合 KV 缓存管理器将块大小调整为较大值时,短前缀可能不会被缓存。--quantization ascend为 W8A8 模型启用 Ascend 量化。部署 BF16 模型时请移除此选项。--speculative-config启用 Qwen3.5 MTP 推测解码。如果工作负载对首 token 延迟敏感,或 MTP 在你的环境中不稳定,请减少num_speculative_tokens或移除此选项。--compilation-config '{"cudagraph_mode":"FULL_DECODE_ONLY"}'启用完整解码 ACLGraph 重放,以减少调度开销。--additional-config启用 Ascend 特定优化。enable_fused_mc2启用 MoE 融合算子,enable_cpu_binding启用 Ascend 原生 CPU 绑定。
5.2 多节点 MP 部署(推荐)¶
多节点 MP 部署在节点之间使用 vLLM 数据并行,在每个节点内部使用张量并行。对于在 2 个 Atlas 800 A2(64GB x 8)节点上部署 W8A8 模型,推荐使用该方式。
假设你有 2 个 Atlas 800 A2 节点,并希望跨这些节点部署 Qwen3.5-397B-A17B-w8a8-mtp。请将 nic_name、local_ip 和 node0_ip 替换为你环境中实际的网络接口和 IP 地址。
在节点 0 上运行以下脚本。
#!/bin/sh
# Get these values through ifconfig.
# nic_name is the network interface name corresponding to local_ip.
nic_name="xxxx"
local_ip="xxxx"
export VLLM_USE_MODELSCOPE=True
export HCCL_BUFFSIZE=1024
export HCCL_IF_IP=$local_ip
export HCCL_SOCKET_IFNAME=$nic_name
export GLOO_SOCKET_IFNAME=$nic_name
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
# Ensure the model path matches the directory recorded during download
vllm serve Eco-Tech/Qwen3.5-397B-A17B-w8a8-mtp \
--host 0.0.0.0 \
--port 8000 \
--data-parallel-size 2 \
--api-server-count 2 \
--data-parallel-size-local 1 \
--data-parallel-address $local_ip \
--data-parallel-rpc-port 13389 \
--seed 1024 \
--served-model-name qwen3.5 \
--tensor-parallel-size 8 \
--enable-expert-parallel \
--max-num-seqs 16 \
--max-model-len 32768 \
--max-num-batched-tokens 4096 \
--trust-remote-code \
--gpu-memory-utilization 0.9 \
--no-enable-prefix-caching \
--quantization ascend \
--speculative-config '{"method": "qwen3_5_mtp", "num_speculative_tokens": 3}' \
--compilation-config '{"cudagraph_mode":"FULL_DECODE_ONLY"}' \
--additional-config '{"enable_cpu_binding":true, "multistream_overlap_shared_expert": true}'
常见问题提示:如果节点 1 无法加入服务或 HCCL 初始化超时,请参考 验证多节点通信环境 和 常见问题。请确保各节点上的网络接口名称、IP 地址和 RPC 端口保持一致。
在节点 1 上运行以下脚本。
#!/bin/sh
# Get these values through ifconfig.
# nic_name is the network interface name corresponding to local_ip.
nic_name="xxxx"
local_ip="xxxx"
export VLLM_USE_MODELSCOPE=True
export HCCL_BUFFSIZE=1024
export HCCL_IF_IP=$local_ip
export HCCL_SOCKET_IFNAME=$nic_name
export GLOO_SOCKET_IFNAME=$nic_name
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
# The value of node0_ip must be consistent with local_ip on node 0.
node0_ip="xxxx"
# Ensure the model path matches the directory recorded during download
vllm serve Eco-Tech/Qwen3.5-397B-A17B-w8a8-mtp \
--host 0.0.0.0 \
--port 8000 \
--headless \
--data-parallel-size 2 \
--data-parallel-size-local 1 \
--data-parallel-start-rank 1 \
--data-parallel-address $node0_ip \
--data-parallel-rpc-port 13389 \
--seed 1024 \
--tensor-parallel-size 8 \
--served-model-name qwen3.5 \
--max-num-seqs 16 \
--max-model-len 32768 \
--max-num-batched-tokens 4096 \
--enable-expert-parallel \
--trust-remote-code \
--gpu-memory-utilization 0.9 \
--no-enable-prefix-caching \
--quantization ascend \
--speculative-config '{"method": "qwen3_5_mtp", "num_speculative_tokens": 3}' \
--compilation-config '{"cudagraph_mode":"FULL_DECODE_ONLY"}' \
--additional-config '{"enable_cpu_binding":true, "multistream_overlap_shared_expert": true}'
常见问题提示:如果无头节点立即退出,请检查节点 0 是否已在运行、--data-parallel-address 是否指向节点 0,以及 --data-parallel-start-rank 在每个节点上是否唯一。
如果服务启动成功,节点 0 上会显示以下信息:
INFO: Started server process [44610]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Started server process [44611]
INFO: Waiting for application startup.
INFO: Application startup complete.
MP 部署的关键参数:
--data-parallel-size是所有节点间的全局 DP 大小。在示例中,使用了 2 个 DP rank。--data-parallel-size-local是当前节点上的 DP rank 数量。在示例中,每个 A2 节点有 1 个本地 DP rank。--data-parallel-start-rank是当前节点上的第一个 DP rank。节点 0 默认从 0 开始,节点 1 从 1 开始。--data-parallel-address必须指向主 DP 节点。在节点 0 上使用节点 0 的local_ip,在其他节点上使用node0_ip。--data-parallel-rpc-port是 DP RPC 端口。在所有节点上使用相同的值,并确保该端口可用。--api-server-count控制在主节点上启动多少个 API 服务器进程。--headless启动一个不暴露 API 服务器的工作节点。在非主节点上使用它。--tensor-parallel-size 8将一个 TP 组映射到每个 A2 节点上的 8 个 NPU。HCCL_IF_IP、GLOO_SOCKET_IFNAME和HCCL_SOCKET_IFNAME将 HCCL 和 Gloo 通信绑定到所选网络。multistream_overlap_shared_expert重叠共享专家计算,以提升 MoE 工作负载的吞吐量。
5.3 多节点 Ray 部署¶
对于基于 Ray 的分布式部署,请参考 Ray 分布式(Qwen/Qwen3-235B-A22B)。相同的模型权重、通信验证和参数调优原则同样适用于 Qwen3.5-397B-A17B。
常见问题提示:如果 Ray 工作节点无法互相发现,请先检查 Ray 集群状态,然后验证与 MP 部署中使用的相同 HCCL 和网络接口设置。
5.4 Prefill-Decode 分离(A3)¶
PD 分离将 Prefill 和 Decode 分离到不同的服务组中。Prefill 节点处理大型 Prompt 块,Decode 节点负责 Token 生成,代理在它们之间转发请求。该模式适用于需要分别调整 Prefill 和 Decode 资源比例的生产服务场景。
我们建议使用 Mooncake 进行部署。有关通用 PD 分离工作流,请参考 Mooncake。
对于 Atlas 800 A3(64G x 16),我们建议为 Qwen3.5-397B-A17B-w8a8-mtp 使用 2 个节点部署 1P1D:
- 1 个 Prefill 节点:1 台 Atlas 800 A3(64G x 16)。
- 1 个 Decode 节点:1 台 Atlas 800 A3(64G x 16)。
在对应节点上部署 run_p.sh 和 run_d.sh,并在 Prefill 主节点上部署代理脚本以转发请求。
5.4.1 Prefill 节点¶
在 Prefill 节点上创建 run_p.sh。
#!/bin/bash
unset ftp_proxy
unset https_proxy
unset http_proxy
# Get these values through ifconfig.
# nic_name is the network interface name corresponding to local_ip.
nic_name="xxxx"
local_ip="xxxx"
export IP_ADDRESS=$local_ip
export NETWORK_CARD_NAME=$nic_name
export HCCL_BUFFSIZE=1536
export HCCL_IF_IP=$IP_ADDRESS
export HCCL_OP_EXPANSION_MODE="AIV"
export HCCL_SOCKET_IFNAME=$NETWORK_CARD_NAME
export ASCEND_RT_VISIBLE_DEVICES=0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
export LD_LIBRARY_PATH=/usr/local/Ascend/ascend-toolkit/latest/python/site-packages:$LD_LIBRARY_PATH
export GLOO_SOCKET_IFNAME=$NETWORK_CARD_NAME
export PYTORCH_NPU_ALLOC_CONF="expandable_segments:True"
# Ensure the model path matches the directory recorded during download
vllm serve Eco-Tech/Qwen3.5-397B-A17B-w8a8-mtp \
--host ${IP_ADDRESS} \
--port 30060 \
--no-enable-prefix-caching \
--enable-expert-parallel \
--data-parallel-size 1 \
--data-parallel-size-local 1 \
--api-server-count 1 \
--data-parallel-address ${IP_ADDRESS} \
--max-num-seqs 64 \
--data-parallel-rpc-port 6884 \
--tensor-parallel-size 16 \
--seed 1024 \
--distributed-executor-backend mp \
--served-model-name qwen3.5 \
--max-model-len 16384 \
--max-num-batched-tokens 4096 \
--trust-remote-code \
--quantization ascend \
--no-disable-hybrid-kv-cache-manager \
--speculative-config '{"method": "qwen3_5_mtp", "num_speculative_tokens": 3, "enforce_eager": true}' \
--additional-config '{"enable_cpu_binding": true}' \
--gpu-memory-utilization 0.9 \
--enforce-eager \
--kv-transfer-config \
'{"kv_connector": "MooncakeLayerwiseConnector",
"kv_role": "kv_producer",
"kv_port": "23010",
"kv_connector_extra_config": {
"prefill": {
"dp_size": 1,
"tp_size": 16
},
"decode": {
"dp_size": 1,
"tp_size": 16
}
}
}'
常见问题提示:如果 Prefill 服务长时间未就绪,请检查模型路径是否已共享、ASCEND_RT_VISIBLE_DEVICES 是否包含全部 16 个 NPU,以及 Mooncake 的 kv_port 是否可用。
5.4.2 Decode 节点¶
在 Decode 节点上创建 run_d.sh。
#!/bin/bash
unset ftp_proxy
unset https_proxy
unset http_proxy
# Get these values through ifconfig.
# nic_name is the network interface name corresponding to local_ip.
nic_name="xxxx"
local_ip="xxxx"
export IP_ADDRESS=$local_ip
export NETWORK_CARD_NAME=$nic_name
export HCCL_BUFFSIZE=1536
export HCCL_IF_IP=$IP_ADDRESS
export HCCL_OP_EXPANSION_MODE="AIV"
export HCCL_SOCKET_IFNAME=$NETWORK_CARD_NAME
export ASCEND_RT_VISIBLE_DEVICES=0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
export LD_LIBRARY_PATH=/usr/local/Ascend/ascend-toolkit/latest/python/site-packages:$LD_LIBRARY_PATH
export GLOO_SOCKET_IFNAME=$NETWORK_CARD_NAME
export PYTORCH_NPU_ALLOC_CONF="expandable_segments:True"
# Ensure the model path matches the directory recorded during download
vllm serve Eco-Tech/Qwen3.5-397B-A17B-w8a8-mtp \
--host ${IP_ADDRESS} \
--port 30050 \
--no-enable-prefix-caching \
--enable-expert-parallel \
--data-parallel-size 1 \
--data-parallel-size-local 1 \
--api-server-count 1 \
--data-parallel-address ${IP_ADDRESS} \
--max-num-seqs 32 \
--data-parallel-rpc-port 6884 \
--tensor-parallel-size 16 \
--seed 1024 \
--distributed-executor-backend mp \
--served-model-name qwen3.5 \
--max-model-len 16384 \
--max-num-batched-tokens 128 \
--trust-remote-code \
--quantization ascend \
--no-disable-hybrid-kv-cache-manager \
--speculative-config '{"method": "qwen3_5_mtp", "num_speculative_tokens": 3}' \
--additional-config '{"recompute_scheduler_enable": true, "enable_cpu_binding": true}' \
--compilation-config '{"cudagraph_mode": "FULL_DECODE_ONLY"}' \
--gpu-memory-utilization 0.96 \
--kv-transfer-config \
'{"kv_connector": "MooncakeLayerwiseConnector",
"kv_buffer_device": "npu",
"kv_role": "kv_consumer",
"kv_port": "36010",
"kv_connector_extra_config": {
"prefill": {
"dp_size": 1,
"tp_size": 16
},
"decode": {
"dp_size": 1,
"tp_size": 16
}
}
}'
常见问题提示:如果 Decode 节点初始化失败,请检查 --tensor-parallel-size 是否为 16、--data-parallel-size-local 是否与全局 Decode DP 大小(1)一致,以及 kv_connector_extra_config.decode.dp_size 是否与全局 Decode DP 大小一致。
PD 分离的关键参数:
--distributed-executor-backend mp在每个节点上使用多进程来运行本地 worker。- Prefill 使用
--data-parallel-size 1、--data-parallel-size-local 1和--tensor-parallel-size 16。这会创建 1 个 DP 组,TP 为 16。 - Decode 使用
--data-parallel-size 1、--data-parallel-size-local 1和--tensor-parallel-size 16。这会创建 1 个本地 DP 组,每个组的 TP 为 16。 --data-parallel-address和--data-parallel-rpc-port定义 DP 控制平面。--max-num-batched-tokens在 Prefill 节点上较大,在 Decode 节点上较小,因为 Prefill 阶段 prompt token 密集,而 Decode 阶段对延迟敏感。- 当 Decode 的 KV cache 不足时,
recompute_scheduler_enable会将请求发回 Prefill 端重新计算 KV cache。在 PD 模式下,仅在 Decode 节点上启用该参数。 --kv-transfer-config设置 Mooncake 连接器。Prefill 上kv_role为kv_producer,Decode 上为kv_consumer。kv_connector_extra_config.prefill.dp_size/tp_size和decode.dp_size/tp_size必须与实际的全局 DP 和 TP 布局一致。--no-enable-prefix-caching禁用前缀缓存。对于 PD 分离,D 节点前缀缓存的已知问题跟踪在 #7944。- 建议在 Decode 节点上使用
--compilation-config '{"cudagraph_mode": "FULL_DECODE_ONLY"}',以减少 Decode 调度开销。
5.5 预填充-解码分离(950DT 产品)¶
对于 950DT 产品(96G x 8),我们建议为 Qwen3.5-397B-A17B-w4a4-mxfp4 部署 2 个节点的 1P1D:
- 1 个预填充节点:1 台 950DT 产品(96G x 8)。运行独立服务,DP=1,TP=8。
- 1 个解码节点:1 台 950DT 产品(96G x 8)。组成全局 DP=1 组,包含 1 个本地 DP rank(TP=8)。
预填充服务通过 Mooncake p2p 连接器将 KV 缓存推送到解码节点。
在相应节点上部署 run_p.sh 和 run_d.sh,并在预填充主节点上部署代理脚本以转发请求。
5.5.1 预填充节点¶
在预填充节点上创建 run_p.sh。
#!/bin/bash
unset ftp_proxy
unset https_proxy
unset http_proxy
source /root/.bashrc
export PROMETHEUS_MULTIPROC_DIR=/dev/shm/vllm_metrics && mkdir -p $PROMETHEUS_MULTIPROC_DIR
# Get these values through ifconfig.
# nic_name is the network interface name corresponding to local_ip.
nic_name="xxx"
local_ip="xxx"
export VLLM_EXECUTE_MODEL_TIMEOUT_SECONDS=30000
export HCCL_BUFFSIZE=300
export HCCL_IF_IP=$local_ip
export HCCL_SOCKET_IFNAME=$nic_name
export ASCEND_RT_VISIBLE_DEVICES=0,1,2,3,4,5,6,7
export DYNAMIC_EPLB="true"
export GLOO_SOCKET_IFNAME=$nic_name
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export HCCL_DFS_CONFIG="task_exception:off,inconsistent_check:off"
export HCCL_ALGO=level0:fullmesh
# Ensure the model path matches the directory recorded during download
vllm serve Eco-Tech/Qwen3.5-397B-A17B-w4a4-mxfp4 \
--host 0.0.0.0 \
--port 30060 \
--no-enable-prefix-caching \
--enable-expert-parallel \
--data-parallel-size 1 \
--data-parallel-size-local 1 \
--data-parallel-address $local_ip \
--data-parallel-rpc-port 6884 \
--tensor-parallel-size 8 \
--seed 1024 \
--distributed-executor-backend mp \
--served-model-name qwen3.5 \
--max-model-len 133000 \
--max-num-batched-tokens 8192 \
--max-num-seqs 64 \
--trust-remote-code \
--gpu-memory-utilization 0.95 \
--quantization ascend \
--async-scheduling \
--enforce-eager \
--speculative-config '{"num_speculative_tokens": 1, "method": "qwen3_5_mtp", "enforce_eager": true}' \
--additional-config '{"enable_cpu_binding": true, "multistream_overlap_shared_expert": true, "recompute_scheduler_enable": true}' \
--kv-transfer-config \
'{"kv_connector": "MooncakeConnector",
"kv_role": "kv_producer",
"kv_port": "30100",
"engine_id": "1",
"kv_connector_module_path": "vllm_ascend.distributed.kv_transfer.kv_p2p.mooncake_connector",
"kv_connector_extra_config": {
"prefill": {
"dp_size": 1,
"tp_size": 8
},
"decode": {
"dp_size": 1,
"tp_size": 8
},
"ascend_local_comm_res_path": "/etc/hixlep"
}
}'
常见问题提示:如果预填充服务长时间未就绪,请检查 ASCEND_RT_VISIBLE_DEVICES 是否包含全部 8 个 NPU、Mooncake kv_port 是否可用,以及 ascend_local_comm_res_path 是否指向可写的共享路径。
5.5.2 解码节点¶
在解码节点上创建 run_d.sh。
#!/bin/bash
unset ftp_proxy
unset https_proxy
unset http_proxy
source /root/.bashrc
export PROMETHEUS_MULTIPROC_DIR=/dev/shm/vllm_metrics && mkdir -p $PROMETHEUS_MULTIPROC_DIR
# Get these values through ifconfig.
# nic_name is the network interface name corresponding to local_ip.
nic_name="xxx"
local_ip="xxx"
export VLLM_EXECUTE_MODEL_TIMEOUT_SECONDS=30000
export HCCL_BUFFSIZE=1200
export HCCL_IF_IP=$local_ip
export HCCL_SOCKET_IFNAME=$nic_name
export ASCEND_RT_VISIBLE_DEVICES=0,1,2,3,4,5,6,7
export DYNAMIC_EPLB="true"
export GLOO_SOCKET_IFNAME=$nic_name
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export HCCL_DFS_CONFIG="task_exception:off,inconsistent_check:off"
export HCCL_ALGO=level0:fullmesh
# Ensure the model path matches the directory recorded during download
vllm serve Eco-Tech/Qwen3.5-397B-A17B-w4a4-mxfp4 \
--host 0.0.0.0 \
--port 30050 \
--no-enable-prefix-caching \
--enable-expert-parallel \
--data-parallel-size 1 \
--data-parallel-size-local 1 \
--api-server-count 1 \
--data-parallel-address $local_ip \
--data-parallel-rpc-port 6884 \
--tensor-parallel-size 8 \
--seed 1024 \
--distributed-executor-backend mp \
--served-model-name qwen3.5 \
--max-model-len 133000 \
--max-num-batched-tokens 240 \
--max-num-seqs 64 \
--trust-remote-code \
--gpu-memory-utilization 0.95 \
--quantization ascend \
--async-scheduling \
--speculative-config '{"num_speculative_tokens": 3, "method": "qwen3_5_mtp"}' \
--compilation-config '{"cudagraph_mode": "FULL_DECODE_ONLY"}' \
--additional-config '{"enable_cpu_binding": true, "multistream_overlap_shared_expert": true, "recompute_scheduler_enable": true, "ascend_compilation_config": {"enable_npugraph_ex": false}}' \
--kv-transfer-config \
'{"kv_connector": "MooncakeConnector",
"kv_role": "kv_consumer",
"kv_port": "30300",
"engine_id": "3",
"kv_connector_module_path": "vllm_ascend.distributed.kv_transfer.kv_p2p.mooncake_connector",
"kv_connector_extra_config": {
"prefill": {
"dp_size": 1,
"tp_size": 8
},
"decode": {
"dp_size": 1,
"tp_size": 8
},
"ascend_local_comm_res_path": "/etc/hixlep"
}
}'
常见问题提示:如果解码节点 0 初始化失败,请检查 --data-parallel-start-rank 是否为 0、--tensor-parallel-size 是否为 8,以及 kv_connector_extra_config.decode.dp_size 是否与全局解码 DP 大小(1)匹配。
5.6 请求转发¶
在与预填充服务实例相同的节点上运行代理服务器。您可以在仓库示例中获取代理程序:load_balance_proxy_server_example.py。
对于 A3 PD 分离(1P1D),代理将请求转发到 1 个预填充节点和 1 个解码节点。使用逐层代理脚本。
unset ftp_proxy
unset https_proxy
unset http_proxy
python3 load_balance_proxy_server_example.py \
--prefiller-hosts 192.xx.xx.1 \
--prefiller-ports 30060 \
--decoder-hosts 192.xx.xx.2 \
--decoder-ports 30050 \
--host 192.xx.xx.1 \
--port 8000
```
例如:
```shell
cd vllm-ascend/examples/disaggregated_prefill_v1/
bash proxy.sh
```
=== "950DT Products"
对于 950DT Products PD 分离(1P1D),代理将请求转发到 1 个 prefill 节点和 1 个 decode 节点。请使用 layerwise 代理脚本。
```shell
unset ftp_proxy
unset https_proxy
unset http_proxy
python3 load_balance_proxy_layerwise_server_example.py \
--prefiller-hosts 192.xx.xx.1 \
--prefiller-ports 30060 \
--decoder-hosts 192.xx.xx.2 \
--decoder-ports 30050 \
--host 192.xx.xx.1 \
--port 8000
```
常见问题提示:如果请求到达代理但未返回输出,请检查代理主机列表是否包含所有健康的 prefill 和 decode 端点,并验证第 6 节中的服务验证请求能否通过代理端口成功执行。
## 6 功能验证 {#6-functional-verification}
服务器启动后,发送一个请求以验证基本模型功能。对于单节点和 MP 部署,请使用节点 0 上的 API 端点。对于 PD 分离,请使用代理端点。
```shell
curl http://<server_ip>:<port>/v1/completions \
-H "Content-Type: application/json" \
-d '{
"model": "qwen3.5",
"prompt": "The future of AI is",
"max_tokens": 50,
"temperature": 0
}'
预期结果:HTTP 状态码为 200,且 JSON 响应中包含带有生成文本的 choices 字段。
7 精度评估¶
以下是两种精度评估方法。
7.1 使用 AISBench¶
- 有关详细信息,请参阅 使用 AISBench。
- 执行后,您可以获取结果。以下
Qwen3.5-397B-A17B-w8a8在vllm-ascend:v0.17.0rc1上的结果仅供参考。
| 数据集 | 版本 | 指标 | 模式 | vllm-api-general-chat |
|---|---|---|---|---|
| gsm8k | - | accuracy | gen | 96.74 |
7.2 使用 Language Model Evaluation Harness¶
有关安装和使用详情,请参阅 使用 lm_eval。使用在线服务时,请将 base_url 设置为第 5 节中启动的端点。
lm_eval \
--model local-completions \
--model_args model=qwen3.5,base_url=http://127.0.0.1:8000/v1/completions,tokenized_requests=False,trust_remote_code=True \
--tasks gsm8k \
--output_path ./
8 性能评估¶
8.1 使用 AISBench¶
有关详细信息,请参阅 使用 AISBench 进行性能评估。
8.2 使用 vLLM Benchmark¶
以运行 Qwen3.5-397B-A17B-w8a8 的性能评估为例。有关更多详情,请参阅 vLLM 基准测试。
vllm bench 有三个子命令:
latency:基准测试单个请求批次的延迟。serve:基准测试在线服务吞吐量。throughput:基准测试离线推理吞吐量。
以 serve 为例:
export VLLM_USE_MODELSCOPE=True
vllm bench serve \
--model Eco-Tech/Qwen3.5-397B-A17B-w8a8-mtp \
--served-model-name qwen3.5 \
--dataset-name random \
--random-input 200 \
--num-prompts 200 \
--request-rate 1 \
--save-result \
--result-dir ./
几分钟后,您可以获取性能评估结果。
9 性能调优¶
9.1 推荐配置¶
以下配置已在特定测试环境中验证,仅供参考。最佳配置取决于硬件类型、最大输入/输出长度、请求并发数、前缀缓存命中率、量化以及 prefill/decode 比例。请根据实际工作负载调整第 9.2 节中的参数。
| 场景 | 部署模式 | NPU 总数 | 权重版本 | 关键考虑因素 |
|---|---|---|---|---|
| 长上下文 | 单节点在线服务 | 16 个 A3 NPU | W8A8 MTP | 使用更大的 --max-model-len 并预留足够的 KV 缓存。如果发生 OOM,请降低 --max-num-seqs。 |
| 长上下文 | 单节点在线服务 | 8 个 950DT Products NPU | W4A4 MXFP4 MTP | 使用 TP=8,并为 133k 上下文预留足够的 KV 缓存。如果发生 OOM,请降低 --max-num-seqs。 |
| 高吞吐 | 多节点 MP | 16 个 A2 NPU | W8A8 MTP | 通过 DP 提高并发,并调整 --max-num-batched-tokens 以优化 prefill 吞吐量。 |
| 低延迟 | 1P1D PD 分离 | 48 个 A3 NPU | W8A8 MTP | 使用独立的 prefill 和 decode DP/TP 布局,并在 decode 节点上启用完整 decode ACLGraph。 |
| 低延迟 | 1P1D PD 分离 | 16 个 950DT Products NPU | W4A4 MXFP4 MTP | 使用一个 8 NPU prefill 节点和一个 8 NPU decode 节点。在 decode 节点上启用完整 decode ACLGraph。 |
| 场景 | 节点角色 | NPU | TP | DP | 最大序列数 | 最大模型长度 | 最大批处理令牌数 | MTP 令牌数 | 前缀缓存 | 主要优化 |
|---|---|---|---|---|---|---|---|---|---|---|
| 长上下文 | 单节点 | 16 | 16 | 1 | 128 | 133000 | 16384 | 3 | 开启 | FullGraph、Fused MC2、CPU 绑定 |
| 高吞吐 | MP 节点 | 每节点 8 | 8 | 每节点 1,全局 2 | 每 DP 16 | 32768 | 4096 | 3 | 关闭 | FullGraph、共享专家重叠、CPU 绑定 |
| 低延迟 | Prefill 节点 | 16 | 2 | 8 | 64 | 16384 | 4096 | 3 | 关闭 | 重计算调度器、Fused MC2、CPU 绑定 |
| 低时延 | Decode节点 | 每节点16 | 2 | 每节点8,全局16 | 32 | 16384 | 128 | 3 | Off | FullGraph、recompute scheduler、Fused MC2、CPU绑定 |
9.2 调优指南¶
通用调优方法请参考公共性能调优文档,功能说明请参考特性矩阵。
推荐的调优顺序:
- 首先设置部署拓扑。验证场景使用单节点部署,简单的多节点服务使用MP部署,当prefill和decode需要不同资源配比时使用PD分离部署。
- 使用
--max-model-len选择最大上下文长度。长上下文会增加KV cache占用,因此发生OOM时请减小--max-num-seqs或--gpu-memory-utilization。 - 调优
--max-num-batched-tokens。较大的值通常能提升prefill吞吐,但会增加激活内存占用。以decode为主的负载通常需要较小的值。 - 根据服务并发度调优
--max-num-seqs。高于该值的请求将在队列中等待,等待时间会计入TTFT和TPOT。 - 调优
--gpu-memory-utilization。增大该值可提供更多KV cache,但需为运行时内存波动和专家负载不均衡预留余量。 - 调优
--speculative-config。MTP可以提升decode吞吐,但最佳num_speculative_tokens取决于接受率和工作负载。 - 调优ACLGraph捕获。decode场景推荐使用
FULL_DECODE_ONLY。如果手动设置cudagraph_capture_sizes,请包含常见的decode批处理大小。使用序列并行时,捕获大小应为TP大小的倍数。
9.3 模型专属优化¶
| 优化项 | 启用方式 | 收益 | 说明 |
|---|---|---|---|
| RoPE优化 | 默认启用 | 跨层复用位置编码计算,降低decode开销。 | 无需额外配置。 |
| AddRMSNormQuant融合 | 默认启用 | 融合归一化和量化操作,减少内存访问。 | 适用于量化路径。 |
| Zero-like消除 | 默认启用 | 移除attention中不必要的zero-like张量操作。 | 无需额外配置。 |
| Qwen3.5 MTP投机解码 | --speculative-config '{"method": "qwen3_5_mtp", "num_speculative_tokens": 3, "enforce_eager": true}' |
在接受率良好时提升decode吞吐。 | 如果时延或稳定性回退,请减少投机token数。 |
| Full decode ACLGraph | --compilation-config '{"cudagraph_mode":"FULL_DECODE_ONLY"}' |
减少算子分发开销,稳定decode性能。 | 推荐用于以decode为主的服务。 |
| Fused MC2 | --additional-config '{"enable_fused_mc2": 1}' |
启用MoE融合算子,提升MoE prefill/decode效率。 | 如果在多DP大token场景下精度或性能回退,请禁用该功能并对比。 |
| Shared expert overlap | --additional-config '{"multistream_overlap_shared_expert": true}' |
在MoE工作负载中重叠共享专家计算。 | 推荐用于MP吞吐场景。 |
| Recompute调度器 | --additional-config '{"recompute_scheduler_enable": true}' |
在PD模式下decode KV cache不足时,通过prefill重计算KV。 | 仅在 kv_role 为 kv_consumer 的decode节点上有效。 |
| CPU绑定 | --additional-config '{"enable_cpu_binding": true}' |
提升CPU亲和性,减少ARM服务器上的调度抖动。 | 许多配置中默认启用,但显式设置可使配置方案更清晰。 |
10 常见问题¶
常见环境、安装和通用参数问题请参考公共FAQ。本节仅介绍Qwen3.5-397B-A17B的模型专属问题。
Q1:为什么服务在启动时或接收请求后不久会报OOM?¶
现象: 服务在profile运行阶段失败,或者启动成功但在真实流量到达时报告OOM。
原因: Qwen3.5-397B-A17B对权重和KV cache的内存需求较高。较大的 --max-model-len、--max-num-seqs、--max-num-batched-tokens 或较高的 --gpu-memory-utilization 可能导致HBM预留空间不足。运行时的专家负载不均衡也可能导致实际推理比profile运行阶段占用更多内存。
解决方案: 尽可能使用带 --quantization ascend 的W8A8模型,降低 --max-model-len、--max-num-seqs、--max-num-batched-tokens,或减小 --gpu-memory-utilization。保持 PYTORCH_NPU_ALLOC_CONF=expandable_segments:True。对于BF16或更大上下文,请使用所需数量的A2/A3节点。
Q2:为什么多节点MP部署在初始化时会卡住?¶
现象: 某个节点等待其他rank,HCCL初始化超时,或headless节点退出。
原因: 各节点的网络接口名称、IP地址、DP rank或RPC端口不一致。
解决方案: 首先验证多节点通信。确保 HCCL_IF_IP、GLOO_SOCKET_IFNAME 和 HCCL_SOCKET_IFNAME 与所选NIC匹配。确保所有节点使用相同的 --data-parallel-rpc-port,非主节点使用 --headless,且 --data-parallel-start-rank 不重叠。
Q3:为什么PD分离示例中禁用了prefix caching?¶
现象: 在decode节点上启用prefix caching时,PD分离部署可能出现异常行为。
原因: D节点的prefix-cache问题是已知限制,跟踪见#7944。
解决方案: 在该限制解决之前,PD分离部署请使用 --no-enable-prefix-caching。对于非PD单节点服务,仅当工作负载存在重复前缀且缓存命中率具有实际意义时,才启用prefix caching。
Q4: 为什么启用序列并行或 Fused MC2 后性能会回退?¶
现象: 启用通信或 MoE 融合优化后,吞吐量下降、延迟增加,或 MoE 负载变得不稳定。
原因: 这些优化依赖于工作负载。序列并行在高并发 TP 场景中最有用。对于某些多 DP 大 token 场景,填充 token 会使某些专家过载,Fused MC2 可能并不适合。
Q5: 应如何为该模型调整 MTP 推测解码?¶
现象: MTP 在某些工作负载中可提高吞吐量,但在其他情况下可能增加首 token 延迟或收益有限。
原因: 收益取决于推测 token 接受率、请求长度和解码并发度。
解决方案: 如本文档所示,先从将 num_speculative_tokens 设置为 3 开始。如果服务对延迟敏感或接受率较低,请降低该值或移除 --speculative-config,并比较 TTFT、TPOT 和吞吐量。
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 vl/vllm-ascend