Qwen3.5-397B-A17B在昇腾A2上部署实践经验师炜文、杨蕾蕾、杨覃娟、刘芮金、谢艺言、刘惠鹏、王剑、陈希迎、周键淇、汤志强
Qwen3.5是阿里于2月16日除夕夜发布的新一代模型,模型整体沿用了Qwen3-next的架构,使用了Gated DeltaNet(线性注意力变体)+ Gated Attention(全注意力/Softmax 类)3:1 配比的混合注意力架构,同时在其基础上进行了扩大词表+原生多模态预训练。 由于采用了线性注意力,且激活值较小,这个模型的主要优势在长文本上。与GLM5作为对比,128k下Qwen3.5的TTFT约为12s,vsGLM5的114s。同时,Qwen3.5 16卡可以最高支持到256k上下文。
为了支持长上下文,选择部署W8A8的量化版本,模型权重可以在魔乐上下载: https://modelers.cn/models/Eco-Tech/Qwen3.5-397B-A17B-w8a8-mtp/tree/main
本文涉及的模型部署均基于1-2台910B2(8-16卡),主要需要的软件依赖为8.5.0版本CANN的配套驱动、固件。 注意:必须使用25.x的驱动及配套固件,24.x驱动会导致模型拉起时卡死
感谢昇腾团队的辛苦付出,在模型发布当天就提供了main2main的Qwen3.5版vllm ascend镜像,可以直接下载使用。路径位于https://modelers.cn/models/Eco-Tech/Qwen3.5-397B-A17B-w8a8-mtp/tree/main 下的vllm-image/文件夹,根据实际机器选择镜像,这里我们用到的是Vllm-ascend-Qwen3_5-A2-Ubuntu-v0.tar。
下载到服务器后,在服务器上执行docker load < /your/path/to/Vllm-ascend-Qwen3_5-A2-Ubuntu-v0.tar导入镜像文件。
创建容器的命令如下:
export IMAGE_ID=6c60d3cc10c2
export NAME=qwen35
docker run -it -d \
--name $NAME --net=host \
--shm-size=500g \
--privileged=true \
--device /dev/davinci0 \
--device /dev/davinci_manager \
--device /dev/devmm_svm \
--device /dev/hisi_hdc \
-v /usr/local/dcmi:/usr/local/dcmi \
-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 /usr/local/Ascend/driver/tools/hccn_tool:/usr/local/Ascend/driver/tools/hccn_tool \
-v /etc/ascend_install.info:/etc/ascend_install.info \
-v /root/.cache:/root/.cache \
-v /etc/hccn.conf:/etc/hccn.conf \
-v /usr/bin/hccn_tool:/usr/bin/hccn_tool \
-v /mnt:/mnt \
--entrypoint=bash $IMAGE_ID \
docker exec -it $NAME bash经验证,16卡A2TP16的部署方案可以拉起模型,128k上下文最高支持5并发,256k最高支持2并发。
#!/bin/bash
nic_name="enpxxxx" # 需要替换
if ! ifconfig $nic_name &>/dev/null; then
echo "error: $nic_name doesn't exist"
exit 1
fi
local_ip=$(ifconfig $nic_name | awk '/inet / {print $2}')
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_BIND=false
export ASCEND_RT_VISIBLE_DEVICES=0,1,2,3,4,5,6,7
export OMP_NUM_THREADS=4
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export HCCL_BUFFSIZE=1024
# export HCCL_OP_EXPANSION_MODE="AIV"
vllm serve ${model_path:="/mnt/esfs/Qwen3.5-397B-A17B-w8a8"} \
--host 0.0.0.0 \
--port 8080 --quantization ascend \
--nnodes 2 \
--master-addr $local_ip \
--master-port 7001 \
--node-rank 0 \
--tensor-parallel-size 16 \
--tool-call-parser qwen3_coder \
--reasoning-parser qwen3 \
--served-model-name qwen35 \
--enable-auto-tool-choice \
--max-model-len 256K \
--max-num-batched-tokens 32768 \
--max-num-seqs 16 \
--trust-remote-code \
--gpu-memory-utilization 0.95 \
--compilation-config '{"cudagraph_mode": "FULL_DECODE_ONLY", "cudagraph_capture_sizes": [1,2,3,4,5,6,8,12,16]}' \
--speculative-config.method mtp \
--speculative-config.num_speculative_tokens 2 \source /usr/local/Ascend/ascend-toolkit/set_env.sh
source /usr/local/Ascend/nnal/atb/set_env.sh
node0_ip=x.x.x.x #需要替换
nic_name="enpxxxx" # 需要替换
if ! ifconfig $nic_name &>/dev/null; then
echo "error: $nic_name doesn't exist"
exit 1
fi
local_ip=$(ifconfig $nic_name | awk '/inet / {print $2}')
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_BIND=false
export ASCEND_RT_VISIBLE_DEVICES=0,1,2,3,4,5,6,7
export OMP_NUM_THREADS=4
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export HCCL_BUFFSIZE=1024
# export HCCL_OP_EXPANSION_MODE="AIV"
# 需要替换
vllm serve ${model_path:="/mnt/esfs/Qwen3.5-397B-A17B-w8a8"} \
--host 0.0.0.0 \
--port 8080 --quantization ascend \
--nnodes 2 \
--master-port 7001 \
--node-rank 1 \
--master-addr $node0_ip \
--headless \
--tensor-parallel-size 16 \
--tool-call-parser qwen3_coder \
--reasoning-parser qwen3 \
--served-model-name qwen35 \
--enable-auto-tool-choice \
--max-model-len 256K \
--max-num-batched-tokens 32768 \
--max-num-seqs 16 \
--trust-remote-code \
--gpu-memory-utilization 0.95 \
--compilation-config '{"cudagraph_mode": "FULL_DECODE_ONLY", "cudagraph_capture_sizes": [1,2,3,4,5,6,8,12,16]}' \
--speculative-config.method mtp \
--speculative-config.num_speculative_tokens 2 \