Qwen3.5 LLM 在 Atlas 300I Duo 上基于 vLLM-Ascend 的部署

Qwen3.5 LLM 在 Atlas 300I Duo 上基于 vLLM-Ascend 的部署操作文档

版本:v0.20.2rc1-310p-openeuler
适用硬件:Atlas 300I Duo(310P3)

一、硬件与软件环境前提

1.1 操作系统与内核要求

项目要求检查命令
操作系统 openEuler 24.03 (LTS-SP3) 或兼容的 ARM64 Linux cat /etc/os-release
内核版本 5.10.0-136.12.0.86.oe2203sp1.aarch64 或更高 uname -r
CPU 架构 aarch64(ARM64) uname -m
Docker 已安装并配置 Ascend 容器运行时 docker info \| grep Runtime

检查示例:

# 检查操作系统
cat /etc/os-release

# 检查内核
uname -r
# 预期输出:5.10.0-136.12.0.86.oe2203sp1.aarch64

# 检查架构
uname -m
# 预期输出:aarch64

1.2 昇腾软件栈版本要求

组件版本说明
CANN 9.1.0-beta.1 Beta 预发布版,必须匹配
驱动(Driver) 25.0.rc1.1 RC 候选版,必须与 CANN 匹配
ATB 9.1.T1 昇腾高性能推理加速库
SOC 版本 ascend310p1 / ascend310p3 Atlas 300I / 310P 推理卡

前置检查命令:

# 检查 CANN 版本
cat /usr/local/Ascend/ascend-toolkit/latest/version.cfg 2>/dev/null || echo "CANN 未安装或路径不一致"

# 检查驱动版本
npu-smi info -t board
# 或
cat /usr/local/Ascend/driver/version.info

# 检查 ATB
find /usr/local/Ascend -name "libatb*" 2>/dev/null | head -5
关键提示:CANN、Driver、ATB 的版本必须严格匹配。本镜像要求 CANN 9.1.0-beta.1 + Driver 25.0.rc1.1,版本不一致会导致容器内 NPU 设备无法识别或推理崩溃。

1.3 NPU 硬件拓扑(300I Duo)

Atlas 300I Duo 为双芯卡,单台服务器通常配备 两张 Duo 卡 = 4 个 NPU Device:

Duo Card 1 (PCIe 0000:01:00.0)
├── Chip 0 → NPU Device 0 (310P3)
│   └── 显存: ~44,280 MB
└── Chip 1 → NPU Device 1 (310P3)
    └── 显存: ~43,693 MB

Duo Card 2 (PCIe 0000:02:00.0)
├── Chip 0 → NPU Device 2 (310P3)
│   └── 显存: ~44,280 MB
└── Chip 1 → NPU Device 3 (310P3)
    └── 显存: ~43,693 MB

查看拓扑命令:

npu-smi info
npu-smi info -t topo

1.4 前置依赖检查清单

在拉取镜像前,请确认以下依赖已就绪:

# 1. Docker 已安装且服务运行
systemctl status docker

# 2. Ascend Docker 运行时已配置
docker info | grep -i " ascend\|runtime"

# 3. NPU 驱动已加载且设备可见
npu-smi info
# 预期看到 4 个 NPU(0/1/2/3),温度与显存信息正常

# 4. 宿主机内存充足(推荐 >= 128GB,本机配置 250GB)
free -h

# 5. 磁盘空间充足(镜像约 194GB,含模型)
df -h /var/lib/docker

二、Docker 镜像来源与获取

2.1 镜像信息

项目内容
官方仓库
推荐标签 v0.20.2rc1-310p-openeuler
版本含义 v0.20.2rc1 = vLLM Ascend RC1;310p = 昇腾 310P;openeuler = 基于 openEuler
镜像大小 约 194 GB(含预置模型文件)
Python 版本 3.11.15
vLLM 版本 0.20.2+empty(源码安装)
vllm-ascend 版本 0.20.2rc1(源码安装)

2.2 拉取镜像

方式一:官方仓库直接拉取(网络通畅时推荐)

docker pull quay.io/ascend/vllm-ascend:v0.20.2rc1-310p-openeuler

方式二:国内镜像加速(网络不佳时)

docker pull m.daocloud.io/quay.io/ascend/vllm-ascend:v0.20.2rc1-310p-openeuler

方式三:从源码自行构建(高级用户)

# 克隆仓库后执行
cd /path/to/vllm-ascend
docker build -f Dockerfile.310p.openEuler -t vllm-ascend:local-310p-openeuler .

2.3 查看可用标签

仓库支持在线查看所有 tag:

https://quay.io/repository/ascend/vllm-ascend?tab=tags

2.4 验证镜像拉取成功

docker images | grep vllm-ascend
# 预期输出包含 quay.io/ascend/vllm-ascend:v0.20.2rc1-310p-openeuler

2.5 镜像内预置内容说明

该镜像为”全量镜像”,内部已预置以下组件:

  • 7 个 Qwen 模型(位于 /models/)
  • 启动脚本(n4.sh, n8.sh, n9.sh, nn9.sh, n27.sh, nn27.sh, n36.sh 等)
  • 华为模型压缩工具msmodelslim-26.0.0-py3-none-any.whl
  • 完整昇腾软件栈(CANN 9.1 Beta、ATB 9.1、torch_npu 2.10.0)
  • vLLM 源码工作区(/vllm-workspace/vllm 和 /vllm-workspace/vllm-ascend)

2.6 POC 镜像与社区版本对比

除 镜像外,社区 Issue #7394 中曾推荐过 POC 430 镜像,两者对比如下:

维度 镜像(本文推荐)POC 430(社区旧版)
镜像标签 v0.20.2rc1-310p-openeuler vllm-ascend_dev-26.0.0.poc.300I-Duo-py311-openEuler24.03-arm
vLLM 版本 0.20.2rc1 ~0.18.x
CANN 版本 9.1.0-beta.1 9.0.T3
稳定性 9B FP16 可稳定运行 27B W8A8 推理易崩溃
文档同步 与镜像版本基本对齐 文档 0.18 与镜像脱节
建议:优先使用本文推荐的 v0.20.2rc1-310p-openeuler 镜像,该版本比 POC 430 新两个大版本,修复了多个已知问题。

2.7 版本差异说明

项目版本说明
官方文档站点 v0.18.0 固定版本 URL,不会自动更新
镜像 v0.20.2rc1 RC 预发布版本,CI 自动构建推送
本文档 v0.20.2rc1 与实际运行容器保持一致
注意:官方文档停留在 0.18.0,但镜像仓库和实际部署已推进到 0.20.x RC。按旧文档操作可能遇到版本不匹配问题。

三、容器运行配置

3.1 Docker 启动参数说明

参数示例值说明
--runtime=ascend 必须 使用昇腾容器运行时,否则无法访问 NPU
--device /dev/davinci* 必须 将 NPU 设备映射进容器
--device /dev/davinci_manager 必须 NPU 管理设备
--device /dev/hisi_hdc 必须 昇腾驱动控制设备
--device /dev/devmm_svm 必须 内存共享设备
-e ASCEND_RT_VISIBLE_DEVICES=0,1 按需 指定容器可见的 NPU 卡号
-p 12320:12320 按需 宿主机端口:容器端口映射
-v /宿主机路径:/容器路径 按需 挂载模型目录或脚本目录
--name 建议 容器命名,务必与内部运行模型一致

3.2 NPU 设备绑定规则

  • 单卡推理(如 4B 模型):ASCEND_RT_VISIBLE_DEVICES=0
  • 双卡 TP2(如 9B、27B 模型):ASCEND_RT_VISIBLE_DEVICES=0,1 或 2,3
  • 四卡 TP4(如 27B 高并发):ASCEND_RT_VISIBLE_DEVICES=0,1,2,3
重要:同一台服务器上的多个 vLLM 容器不能共用 NPU,必须各自独占。例如容器 A 用卡 0,1,容器 B 用卡 2,3。

3.3 可直接使用的 docker run 示例

示例 A:启动 Qwen3.5-9B 服务(双卡 TP2,端口 12322)

docker run -itd \
  --runtime=ascend \
  --name vllm-ascend-qwen3.5-9b \
  --device /dev/davinci0 \
  --device /dev/davinci1 \
  --device /dev/davinci_manager \
  --device /dev/hisi_hdc \
  --device /dev/devmm_svm \
  -e ASCEND_RT_VISIBLE_DEVICES=2,3 \
  -p 12322:12320 \
  -v /root/hxp/models:/models/scripts:ro \
  --memory=250g \
  quay.io/ascend/vllm-ascend:v0.20.2rc1-310p-openeuler \
  bash
参数选择依据:
  • --runtime=ascend:必须,否则容器内看不到 NPU。
  • ASCEND_RT_VISIBLE_DEVICES=2,3:本机卡 0,1 已被另一个 vLLM 容器占用,因此 9B 服务绑定到卡 2,3。
  • -p 12322:12320:宿主机 12322 映射到容器内 12320,避免与已有服务(12320)端口冲突。
  • --memory=250g:宿主机内存充裕(250GB),不设限可能导致容器争抢;此处与宿主机对齐,可根据实际调整。
  • --name 务必反映真实模型,避免运维混淆。

 

示例 B:启动 qwen3.5-27B-w8a8 服务(双卡 TP2,端口 12320)

docker run -itd \
  --runtime=ascend \
  --name vllm-ascend-qwen3.5-27b \
  --device /dev/davinci0 \
  --device /dev/davinci1 \
  --device /dev/davinci_manager \
  --device /dev/hisi_hdc \
  --device /dev/devmm_svm \
  -e ASCEND_RT_VISIBLE_DEVICES=0,1 \
  -p 12320:12320 \
  -v /root/hxp/models:/models/scripts:ro \
  --memory=250g \
  quay.io/ascend/vllm-ascend:v0.20.2rc1-310p-openeuler \
  bash

3.4 进入容器并检查环境

# 进入容器
docker exec -it vllm-ascend-qwen3.5-9b bash

# 容器内检查 NPU 是否可见
npu-smi info

# 检查预置模型
ls -lh /models/

# 检查启动脚本
ls -lh /root/hxp/models/*.sh

四、模型文件准备

4.1 本机实际支持的 Qwen3.5 / qwen3.5 模型变体

镜像 /models/ 目录下已预置以下模型:

模型路径参数规模量化状态推荐 TP适用场景
/models/Qwen3-4B-Instruct-2507 4B FP16(无量化) TP1 轻量推理、边缘部署
/models/Qwen3-8B-w8a8sc-310-vllm 8B W8A8 量化 TP2 需 --quantization ascend
/models/Qwen3.5-0.8B 0.8B FP16 TP1 轻量任务 / draft model
/models/Qwen3.5-9B 9B FP16(无量化) TP2 当前稳定运行的主力模型
/models/Qwen3.5-9B-W8A8 9B W8A8 量化 TP2 显存受限时更优
/models/qwen3.5-27B-w8a8 27B W8A8 量化 TP2/TP4 大模型推理
/models/qwen3.5-35B-A3B-w8a8 35B MOE W8A8 量化 TP2 MOE 专家模型

4.1.1 社区官方支持的 Qwen3.5 模型矩阵(Issue #7394)

社区维护者在 Issue #7394 中给出的官方支持矩阵如下(如需从 ModelScope 下载):

模型量化300I DUO 推荐配置权重来源图模式
Qwen3.5-2B W8A8 TP1 ModelScope 支持
Qwen3.5-4B W8A8 TP1 ModelScope 支持
Qwen3.5-27B W8A8 TP2/TP4 ModelScope 支持(TP 切分受限)
qwen3.5-27B W8A8 TP2/TP4 ModelScope 支持(TP 切分受限)
注意:社区矩阵中 27B 模型的 TP 切分标注为”受限支持”,实际部署时建议先用 TP2 验证稳定性。

4.2 模型选择与显存估算

以 Atlas 300I Duo(单 Chip 约 44GB 显存)为例:

模型精度单卡显存占用(TP2 分摊后)是否需要量化
Qwen3.5-9B FP16 ~9 GB / 卡 可不量化
Qwen3.5-9B W8A8 ~5 GB / 卡 显存更省
qwen3.5-27B FP16 ~27 GB / 卡 接近上限,建议量化
qwen3.5-27B W8A8 ~14 GB / 卡 推荐
选择依据:310P 单 Chip 显存约 44GB,但需预留 KV Cache、图模式缓存及系统开销。27B FP16 在 TP2 下每张卡约 27GB,加上 KV Cache 和图缓存后很容易触及上限,因此 27B 必须使用 W8A8 量化。

4.3 权重量化(如需自行量化)

镜像内已预置 msmodelslim,如需对下载的 FP16 权重进行 W8A8 量化:

# 在容器内执行
pip install /path/to/msmodelslim-26.0.0-py3-none-any.whl

# 使用 msmodelslim 量化(示例,具体参数请参考官方文档)
python -m msmodelslim \
  --model_type Qwen3.5-9B \
  --input_dir /models/Qwen3.5-9B \
  --output_dir /models/Qwen3.5-9B-W8A8 \
  --w8a8

4.4 分片权重与 --load_format 注意事项

对于已按 TP 切分的量化模型(如 Qwen3-8B-w8a8sc-310-vllm/TP2/...),启动时必须指定:

--load_format="sharded_state"

否则 vLLM 会尝试加载完整权重,导致 TP 切分不匹配而启动失败。


五、vLLM 服务启动配置

5.1 启动前必读:配置昇腾环境变量

在容器内执行 vllm serve 前,必须先配置以下环境变量:

export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export HCCL_BUFFSIZE=512
export OMP_PROC_BIND=false
export OMP_NUM_THREADS=1
export TASK_QUEUE_ENABLE=1
export HCCL_OP_EXPANSION_MODE="AIV"
作用说明:
  • PYTORCH_NPU_ALLOC_CONF=expandable_segments:True:启用 PyTorch NPU 内存的可扩展段分配,避免分配失败导致 OOM。
  • HCCL_BUFFSIZE=512:集合通信缓冲区设为 512MB,保证 TP 多卡间通信稳定。
  • OMP_NUM_THREADS=1:限制 OpenMP 线程数为 1,防止与 vLLM 内部线程竞争。
  • TASK_QUEUE_ENABLE=1:启用昇腾任务队列优化,提升调度效率。
  • HCCL_OP_EXPANSION_MODE=AIV:使用 AI Vector 模式扩展 HCCL 算子。

 

5.2 Qwen3.5-9B 完整启动命令(推荐配置)

以下命令来自实际稳定运行的容器 vllm-ascend-qwen3.5(内部运行 Qwen3.5-9B),可直接复制使用:

# 进入容器
docker exec -it vllm-ascend-qwen3.5-9b bash

# 配置环境变量
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export HCCL_BUFFSIZE=512
export OMP_PROC_BIND=false
export OMP_NUM_THREADS=1
export TASK_QUEUE_ENABLE=1
export HCCL_OP_EXPANSION_MODE="AIV"

# 启动服务
ASCEND_RT_VISIBLE_DEVICES=2,3 \
  vllm serve /models/Qwen3.5-9B \
  --host 0.0.0.0 \
  --port 12320 \
  -tp 2 \
  --served-model-name qwen3.5-9b \
  --trust-remote-code \
  --max_num_seqs 8 \
  --gpu_memory_utilization 0.6 \
  --additional-config '{"ascend_compilation_config": {"fuse_norm_quant": false}}' \
  --dtype float16 \
  --compilation-config '{"cudagraph_mode": "FULL_DECODE_ONLY", "cudagraph_capture_sizes": [1,4]}' \
  --allowed-local-media-path / \
  --mamba-ssm-cache-dtype float16 \
  --reasoning-parser qwen3 \
  --enable-auto-tool-choice \
  --tool-call-parser qwen3_coder \
  --enable-chunked-prefill \
  --max-model-len 53248 \
  --enable-prefix-caching \
  --mamba-cache-mode align
若宿主机端口映射为 12322:12320,外部访问时请使用 12322。

5.3 关键参数逐一说明

5.3.1 基础服务参数

参数值说明
--host 0.0.0.0 监听所有网卡 允许宿主机及其他机器访问
--port 12320 容器内服务端口 通过 -p 映射到宿主机外部端口
--served-model-name qwen3.5-9b API 对外模型名 客户端请求时必须使用此名称,而非容器名或路径名
--trust-remote-code 启用 Qwen3.5 需要加载自定义 attention 实现,必须开启

5.3.2 硬件与并行配置

参数值说明
-tp 2 / --tensor-parallel-size 2 张量并行数 2 9B 模型在 310P 上推荐 TP2,两张卡各分摊约 9GB 权重
--gpu_memory_utilization 0.6 显存利用率 60% 保守设置,预留 40% 给 KV Cache、图缓存和系统缓冲,避免 OOM
为什么 gpu_memory_utilization=0.6?
实测中 310P 的显存除了模型权重外,还需容纳 CUDA Graph 缓存、KV Cache、以及昇腾驱动的临时缓冲区。设为 0.6 是为了在 53K 长上下文和图模式同时启用时仍有足够余量。如果业务上下文较短(如 4K 以内),可尝试提升至 0.8。

5.3.3 图模式编译配置(310P 关键优化)

--compilation-config '{"cudagraph_mode": "FULL_DECODE_ONLY", "cudagraph_capture_sizes": [1,4]}'
子参数值说明
cudagraph_mode FULL_DECODE_ONLY 仅在 Decode 阶段启用图模式。310P 上 Prefill 阶段图捕获开销大且收益低,FULL_DECODE_ONLY 是推荐模式
cudagraph_capture_sizes [1,4] 捕获 batch size 为 1 和 4 的计算图。当前 max_num_seqs=8,但 capture_sizes 仅到 4,高并发时部分请求会回退到 eager 模式
优化建议:如需支持 8 并发全图加速,可将 capture_sizes 扩展为 [1,2,4,8]。

5.3.4 昇腾专属编译配置

--additional-config '{"ascend_compilation_config": {"fuse_norm_quant": false}}'
  • fuse_norm_quant: false:禁用 Norm 与 Quant 的算子融合。在 310P 上,融合后可能引入精度损失或编译失败,关闭后更稳定。

5.3.5 上下文长度与缓存优化

参数值说明
--max-model-len 53248 最大 53K tokens 支持长文档或长对话。若显存紧张,可降至 10240 或 40960
--enable-chunked-prefill 启用 分块预填充:将长输入的 Prefill 拆分为多个 chunk,降低首 token 延迟(TTFT)
--enable-prefix-caching 启用 前缀缓存:多轮对话中若存在相同 system prompt 或前缀,可复用 KV Cache,降低 TTFT 和显存占用
--mamba-cache-mode align 启用 Mamba 缓存对齐模式(优化 SSM 状态缓存,对 Transformer 模型无负面影响)
VLLM_ALLOW_LONG_MAX_MODEL_LEN:当 max-model-len 超过模型默认配置时,需前置环境变量 VLLM_ALLOW_LONG_MAX_MODEL_LEN=1。本机 9B 模型使用 53248 未触发此限制,但 8B 量化模型需要。

5.3.6 Qwen3 特有推理与工具解析

参数值说明
--reasoning-parser qwen3 启用 Qwen3 思维链解析 自动分离 <think>...</think> 推理内容
--enable-auto-tool-choice 启用自动工具选择 模型可自主决定是否调用工具
--tool-call-parser qwen3_coder 工具调用解析器 使用 Qwen3 Coder 风格的 tool-call 格式解析

5.3.7 其他参数

参数值说明
--max_num_seqs 8 最大 8 条并发序列 同时处理的请求数上限
--dtype float16 FP16 精度 9B 模型 FP16 可在 310P 上稳定运行
--allowed-local-media-path / 允许访问根目录 多模态场景下允许读取本地媒体文件
--mamba-ssm-cache-dtype float16 Mamba 缓存 FP16 即使非 Mamba 模型,也无副作用

5.4 不同模型的启动命令参考

qwen3.5-27B-w8a8(W8A8 量化,双卡 TP2)

export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export HCCL_BUFFSIZE=512
export OMP_PROC_BIND=false
export OMP_NUM_THREADS=1
export TASK_QUEUE_ENABLE=1
export HCCL_OP_EXPANSION_MODE="AIV"

ASCEND_RT_VISIBLE_DEVICES=0,1 \
  vllm serve /models/qwen3.5-27B-w8a8 \
  --host 0.0.0.0 --port 12320 -tp 2 \
  --served-model-name qwen3.5-27b \
  --trust-remote-code \
  --max_num_seqs 8 \
  --gpu_memory_utilization 0.8 \
  --dtype float16 \
  --compilation-config '{"cudagraph_mode": "FULL_DECODE_ONLY", "cudagraph_capture_sizes": [1,4]}' \
  --allowed-local-media-path / \
  --mamba-ssm-cache-dtype float16 \
  --reasoning-parser qwen3 \
  --enable-auto-tool-choice \
  --tool-call-parser qwen3_coder \
  --max-model-len 40960 \
  --enable-chunked-prefill \
  --enable-prefix-caching
27B 使用 gpu_memory_utilization=0.8:W8A8 量化后权重显存占用大幅降低(约 14GB/卡),因此可以提高显存利用率以增加 KV Cache 容量。

Qwen3-8B-w8a8sc(W8A8 量化,分片权重,双卡 TP2)

export VLLM_ALLOW_LONG_MAX_MODEL_LEN=1
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export HCCL_BUFFSIZE=512
export OMP_PROC_BIND=false
export OMP_NUM_THREADS=1
export TASK_QUEUE_ENABLE=1
export HCCL_OP_EXPANSION_MODE="AIV"

ASCEND_RT_VISIBLE_DEVICES=0,1 \
  vllm serve /models/Qwen3-8B-w8a8sc-310-vllm/TP2/Qwen3-8B-w8a8sc-310-vllm-tp2 \
  --host 0.0.0.0 --port 12320 \
  --tensor-parallel-size 2 \
  --gpu_memory_utilization 0.90 \
  --served_model_name qwen3-8b \
  --dtype float16 \
  --additional-config '{"ascend_compilation_config": {"fuse_norm_quant": false}}' \
  --compilation-config '{"cudagraph_mode": "FULL_DECODE_ONLY", "cudagraph_capture_sizes": [1,2,4,8]}' \
  --quantization ascend \
  --max-model-len 53248 \
  --enable-chunked-prefill \
  --max-num-batched-tokens 4096 \
  --max-num-seqs 40 \
  --enable-prefix-caching \
  --load_format="sharded_state"
注意:8B 量化模型路径指向 TP2 分片子目录,且必须加 --load_format="sharded_state" 和 --quantization ascend。

5.5 社区推荐启动命令参考(Issue #7394)

社区在 Issue #7394 中给出的 Qwen3.5-2B-W8A8 推荐启动命令如下,可供小模型部署参考:

vllm serve /share/weight/Qwen3.5-2B-W8A8/ \
  --host 127.0.0.1 \
  --port 1025 \
  --dtype float16 \
  --served-model-name qwen3.5 \
  --trust-remote-code \
  --max-model-len 10240 \
  --gpu_memory_utilization 0.80 \
  --additional-config '{"ascend_compilation_config": {"fuse_norm_quant": false}}' \
  --compilation-config '{"cudagraph_mode": "FULL_DECODE_ONLY", "cudagraph_capture_sizes": [1,2,4,8,16]}' \
  --mamba-ssm-cache-dtype float16 \
  --allowed-local-media-path /
关键差异:社区推荐 max-model-len 10240(10K 级别),gpu_memory_utilization 0.80,capture_sizes [1,2,4,8,16]。小模型可适当放宽,大模型建议保守设置。

六、昇腾专属环境变量汇总

以下环境变量在启动 vLLM 服务前必须设置:

# 内存与分配
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True

# 集合通信
export HCCL_BUFFSIZE=512
export HCCL_OP_EXPANSION_MODE="AIV"

# OpenMP 线程控制
export OMP_PROC_BIND=false
export OMP_NUM_THREADS=1

# 昇腾任务队列优化
export TASK_QUEUE_ENABLE=1
环境变量推荐值作用
PYTORCH_NPU_ALLOC_CONF expandable_segments:True NPU 内存可扩展段分配,降低 OOM 概率
HCCL_BUFFSIZE 512 设置 HCCL 通信缓冲区大小(MB)
HCCL_OP_EXPANSION_MODE AIV HCCL 算子扩展模式,使用 AI Vector 加速
OMP_PROC_BIND false 禁止 OpenMP 线程绑定到固定 CPU 核心,避免调度冲突
OMP_NUM_THREADS 1 每个进程只使用 1 个 OpenMP 线程,防止与 vLLM 内部线程竞争
TASK_QUEUE_ENABLE 1 启用昇腾任务队列,提升算子下发效率
VLLM_ALLOW_LONG_MAX_MODEL_LEN 1(按需) 允许设置超过模型默认配置的最大上下文长度
ASCEND_RT_VISIBLE_DEVICES 0,1 / 2,3 等 指定容器内可见的 NPU 设备
设置方式:建议在启动脚本(如 n9.sh、n27.sh)开头统一 export,或在 docker run 时通过 -e 传入。

七、服务验证与测试

7.1 检查容器状态

# 查看容器是否运行
docker ps | grep vllm-ascend

# 预期输出示例
# vllm-ascend-qwen3.5-9b   quay.io/ascend/vllm-ascend:v0.20.2rc1-310p-openeuler   Up 10 minutes   12322->12320/tcp

7.2 检查 NPU 占用

# 宿主机执行
npu-smi info

# 或查看进程级占用
npu-smi info -t processes

预期输出特征:

+----------------------------------------------------------------------------------+
| NPU     Name           |  Health   | Power(W)   | Temp(C)   | Memory-Usage(MB)  |
| 0       Ascend310P3    |  OK       | 12.0       | 52        | 43624/44280       |
| 1       Ascend310P3    |  OK       | 11.8       | 49        | 43008/43693       |
  • Health 应为 OK
  • 显存应有明显占用(如 39GB~42GB),说明模型已加载
  • 温度正常范围 40C~60C

7.3 查看服务日志

# 实时跟踪日志
docker logs -f --tail 100 vllm-ascend-qwen3.5-9b

# 或进入容器查看 vLLM 输出
docker exec -it vllm-ascend-qwen3.5-9b bash
# 若服务在后台运行,可通过 ps + grep 找到 vllm serve 进程
ps aux | grep vllm

日志关键指标(服务正常运行后会周期性输出):

Engine 000: Avg prompt throughput: 1403.7 tokens/s,
            Avg generation throughput: 17.0 tokens/s,
            Running: 1 reqs, Waiting: 0 reqs,
            GPU KV cache usage: 1.5%,
            Prefix cache hit rate: 0.0%
指标健康范围说明
Avg prompt throughput > 500 tokens/s Prefill 阶段吞吐,单请求通常 1000+
Avg generation throughput 4~20 tokens/s Decode 阶段吞吐,9B 约 17,27B 约 4~5
GPU KV cache usage < 90% KV Cache 占用比例,接近 100% 有 OOM 风险
Prefix cache hit rate 视业务而定 多轮对话共享前缀时应有提升

7.4 OpenAI 兼容 API 调用示例

vLLM 提供 OpenAI 兼容的 /v1/chat/completions 接口。

# 测试对话(注意:模型名必须与 --served-model-name 完全一致)
curl http://localhost:12322/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "qwen3.5-9b",
    "messages": [
      {"role": "system", "content": "You are a helpful assistant."},
      {"role": "user", "content": "你好,请介绍一下自己。"}
    ],
    "max_tokens": 512,
    "temperature": 0.7
  }'
常见 404 错误:如果返回 The model 'xxx' does not exist,请检查:
  1. 请求中的 model 字段是否等于 --served-model-name 的值
  2. 端口是否正确(宿主机端口 vs 容器内端口)
  3. 容器名与实际模型是否被混淆(本机曾出现 vllm-ascend-qwen3 容器实际跑的是 27B 模型的情况)

 

7.5 验证推理吞吐和 KV Cache

使用 vLLM 自带的 benchmark 工具或持续观察日志:

# 方式一:查看实时日志中的吞吐指标
docker logs -f vllm-ascend-qwen3.5-9b | grep "Avg generation throughput"

# 方式二:使用 benchmark_serving.py(若容器内有该脚本)
python /vllm-workspace/vllm/benchmarks/benchmark_serving.py \
  --host localhost \
  --port 12322 \
  --model qwen3.5-9b \
  --dataset-name random \
  --num-prompts 100

八、已知问题、风险提示与排查

8.1 软件栈稳定性状态

组件版本状态风险等级
vLLM Ascend 镜像 v0.20.2rc1(RC 候选版) 中
CANN 9.1.0-beta.1(Beta 版) 中
Driver 25.0.rc1.1(RC 候选版) 中
transformers 5.5.3(华为内部修改版) 中

结论:整套软件栈处于预发布阶段,适合测试验证,不建议直接用于生产环境。

8.2 310P 硬件硬功能限制

限制项影响说明
SpecDecoding / 投机解码 不支持 任何触发 AscendAttentionState.SpecDecoding 的代码路径都会抛出 NotImplementedError
MTP(Multi-Token Prediction) 不支持 与 SpecDecoding 相关,310P 上无法启用
Chunk-gated-delta-rule 合入中 chunk-gated-delta-rule 尚未完全合入 main 分支
MOE 结构(35B A3B) 未明确 未在社区支持矩阵中明确列出
TP 切分(27B 模型) 受限 大模型在 TP2/TP4 下的图模式切分存在已知限制

社区实测崩溃案例(Issue #7394)

社区成员在 Atlas 300i Pro(同为 310P3 芯片)上使用 POC 430 镜像测试 Qwen3.5-27B W8A8 时,出现致命崩溃:

  • 服务可以启动并监听端口,但一旦触发推理请求立即崩溃。
  • 错误根因: NotImplementedError: AscendAttentionState.SpecDecoding is not supported for 310P currently.
  • 该用户尝试了多个量化版本(w8a8、w8a8s、w8a8sc)、多款模型(Qwen3 32B、Qwen3.5 27B)、多个镜像版本(0.13.0 -> 0.18.0-310p),均无法稳定运行。

为什么本地 9B FP16 能稳定运行而社区 27B W8A8 崩溃?

维度社区崩溃环境(Issue #7394)本地稳定环境
镜像版本 POC 430 / 0.18.x v0.20.2rc1
CANN 版本 9.0.T3 / 9.1.0.beta1 9.1.0-beta.1
运行模型 Qwen3.5-27B(W8A8) Qwen3.5-9B(FP16)
模型大小 27B 量化 9B 非量化
是否触发 SpecDecoding 是(W8A8 量化路径) 否(FP16 常规路径)
状态 一触即发就崩 已稳定运行数天

核心差异:

  1. 版本代差:本地 v0.20.2rc1 比 POC 430 新两个大版本,修复了多个已知问题。
  2. 模型差异:9B FP16 在 2 卡 TP 下每张卡约 9GB,压力远小于 27B。
  3. 量化与 SpecDecoding:社区崩溃的核心是 SpecDecoding is not supported for 310P。本地环境没有启用 speculative decode/MTP,且 --dtype float16 走常规路径,因此绕过了这个坑。

排查命令:

若服务启动后一推理就崩溃,检查日志是否包含:

NotImplementedError: AscendAttentionState.SpecDecoding is not supported for 310P currently.

解决方案:确保启动命令中没有 --speculative-model、-speculative-config 等投机解码参数。建议优先使用 9B 及以下 FP16 模型进行验证,待软件栈成熟后再尝试 27B W8A8。

8.3 容器名与模型名不匹配陷阱

本机实际运行环境曾出现以下混淆:

容器名实际运行模型对外模型名端口
vllm-ascend-qwen3 qwen3.5-27B-w8a8 qwen3.5-27b 12320
vllm-ascend-qwen3.5 Qwen3.5-9B qwen3.5-9b 12322

风险:运维人员可能根据容器名判断模型类型,导致 API 请求使用错误的模型名而返回 404。

建议:新建容器时,务必让 --name 与实际模型一致,例如:

  • 跑 Qwen3.5-9B 的容器命名为 vllm-ascend-qwen3.5-9b
  • 跑 qwen3.5-27B 的容器命名为 vllm-ascend-qwen3.5-27b

8.4 常见启动失败原因及解决方案

现象可能原因解决方案
容器内 npu-smi info 无输出 未使用 --runtime=ascend 或设备映射缺失 检查 docker run 是否有 --runtime=ascend 和 --device /dev/davinci*
启动时 OOM / 显存不足 gpu_memory_utilization 过高或 max-model-len 过长 降低 gpu_memory_utilization(如 0.6)或缩短 max-model-len
模型加载失败 / 形状不匹配 使用了分片权重但未加 --load_format="sharded_state" 量化 TP 模型必须加 --load_format="sharded_state"
推理时崩溃 NotImplementedError: SpecDecoding 模型配置或代码路径触发了投机解码 移除所有 speculative decode 参数,使用常规推理
API 返回 404 model does not exist 请求中的 model 字段与 --served-model-name 不一致 统一名称,或查询 :port/v1/models 确认可用模型
高并发下吞吐扩展性差 cudagraph_capture_sizes 未覆盖实际并发数 扩展为 [1,2,4,8] 或 [1,2,4,8,16]
Prefix Cache 命中率始终为 0 请求间无共享前缀,或功能未生效 确保请求包含相同 system prompt;检查 --enable-prefix-caching 是否已加

8.5 端口冲突排查

除 4.sh 使用 12322 外,大部分脚本默认使用 12320。同一宿主机上同时启动多个 vLLM 容器时,必须映射到不同宿主机端口:

# 服务 A(9B 模型)
-p 12320:12320

# 服务 B(27B 模型)
-p 12321:12320

# 服务 C(4B 模型)
-p 12322:12320

九、版本差异与镜像选择建议

9.1 RFC 完成度评估(Issue #7394)

提案项状态备注
W8A8 量化 部分支持 有量化工具和权重,但大模型(27B)推理不稳定
MTP/投机解码 不支持 SpecDecoding 在 310P 上直接报 NotImplementedError
Gated Delta Rule 合入中 chunk-gated-delta-rule 尚未完全合入 main
MOE 结构 未明确 35B A3B 等 MOE 模型未在支持矩阵中明确列出
Mamba Cache 部分支持 PR #7372 已关联,但 300I Duo 上图模式受限
Ascend C 算子 未公开 社区不可见
E2E CI 未达成 社区用户实测频繁崩溃

9.2 当前落地风险总结

  • 边缘计算场景要求稳定,但当前软件栈全是 RC/Beta:CANN 9.1 Beta、Driver 25.0 RC、vllm-ascend 0.20.2rc1。
  • 310P 的 Attention 实现存在硬缺口:SpecDecoding 不支持,导致任何触发投机解码路径的模型都会崩溃。
  • 文档与镜像严重脱节:官方文档停留在 0.18.0,而镜像已推进到 0.20.2rc1,社区用户按旧文档操作必然踩坑。
  • TP 切分受限:27B 模型在 TP2/TP4 下”受限支持”,说明分布式推理在 310P 上尚未成熟。

9.3 镜像与模型选择决策树

新手上路 / 验证测试
    │
    ├── 推荐镜像: v0.20.2rc1-310p-openeuler (本文)
    │   └── 不推荐 POC 430(版本旧、问题多)
    │
    ├── 推荐模型: Qwen3.5-9B FP16 (TP2)
    │   └── 显存占用低、路径常规、绕过 SpecDecoding 坑
    │
    └── 不推荐: Qwen3.5-27B W8A8
        └── 易触发 SpecDecoding 崩溃,TP 切分受限

进阶探索(软件栈更新后)
    │
    ├── 关注 Issue #9711 获取正式版进度
    └── 等待 CANN 正式版 + 驱动稳定版后再上生产

9.4 后续跟踪


附录:快速启动检查清单

在全新服务器上按顺序执行:

# 1. 检查硬件与驱动
npu-smi info

# 2. 拉取镜像
docker pull quay.io/ascend/vllm-ascend:v0.20.2rc1-310p-openeuler

# 3. 启动容器(以 Qwen3.5-9B 为例)
docker run -itd \
  --runtime=ascend \
  --name vllm-ascend-qwen3.5-9b \
  --device /dev/davinci2 \
  --device /dev/davinci3 \
  --device /dev/davinci_manager \
  --device /dev/hisi_hdc \
  --device /dev/devmm_svm \
  -e ASCEND_RT_VISIBLE_DEVICES=2,3 \
  -p 12322:12320 \
  quay.io/ascend/vllm-ascend:v0.20.2rc1-310p-openeuler \
  bash

# 4. 进入容器
docker exec -it vllm-ascend-qwen3.5-9b bash

# 5. 设置环境变量并启动服务
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export HCCL_BUFFSIZE=512
export OMP_PROC_BIND=false
export OMP_NUM_THREADS=1
export TASK_QUEUE_ENABLE=1
export HCCL_OP_EXPANSION_MODE="AIV"

ASCEND_RT_VISIBLE_DEVICES=2,3 \
  vllm serve /models/Qwen3.5-9B \
  --host 0.0.0.0 --port 12320 -tp 2 \
  --served-model-name qwen3.5-9b \
  --trust-remote-code \
  --max_num_seqs 8 \
  --gpu_memory_utilization 0.6 \
  --additional-config '{"ascend_compilation_config": {"fuse_norm_quant": false}}' \
  --dtype float16 \
  --compilation-config '{"cudagraph_mode": "FULL_DECODE_ONLY", "cudagraph_capture_sizes": [1,4]}' \
  --allowed-local-media-path / \
  --mamba-ssm-cache-dtype float16 \
  --reasoning-parser qwen3 \
  --enable-auto-tool-choice \
  --tool-call-parser qwen3_coder \
  --enable-chunked-prefill \
  --max-model-len 53248 \
  --enable-prefix-caching \
  --mamba-cache-mode align

# 6. 新开终端验证服务
curl http://localhost:12322/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{"model":"qwen3.5-9b","messages":[{"role":"user","content":"你好"}]}'

 

参考:

快速入门 — vllm-ascend

https://github.com/vllm-project/vllm-ascend/issues/9711

posted @ 2026-06-14 20:12  鹏小鹕  阅读(1064)  评论(1)    收藏  举报