vLLM Ascend 在 Atlas 300I DUO 上的 CANN 容器环境搭建与推理实战
vLLM Ascend 在 Atlas 300I DUO 上的 CANN 容器环境搭建与推理实战
本指南完整讲解如何在华为 Atlas 300I DUO 推理加速卡上,通过 CANN 官方基础镜像为 vLLM Ascend 搭建可运行的 Docker 容器环境:从镜像拉取、容器启动参数逐项解析、环境验证,到容器内安装 vLLM 与 vLLM Ascend,最后结合该硬件特有的运行约束跑通离线推理与在线服务。文章内容以仓库文档 atlas-300i-duo.inc.md 为骨架,并补充了源码与配置层面的佐证,读者按步骤操作即可在 300I DUO 上完成一次真实推理。
一、Atlas 300I DUO 在 vLLM Ascend 支持矩阵中的定位
Atlas 300I DUO 与 Atlas 200I Pro 同属"Atlas inference series products(Atlas 推理系列产品)",是昇腾生态中的推理加速硬件。在 vLLM Ascend 官方支持矩阵中,这两款硬件使用 310p 构建标识与软件栈:
| 硬件类型 | 代表性产品 | 软件构建标识 |
|---|---|---|
| Atlas A2 系列 | Atlas 800T A2、Atlas 300T A2 等 | 910b / A2 |
| Atlas A3 系列 | Atlas 800T A3、Atlas 900 A3 SuperPoD 等 | a3 |
| Atlas 推理系列 | Atlas 300I DUO、Atlas 200I Pro | 310p |
| 950DT 产品 | 950DT | 950 |
以上硬件分类详见仓库文档 supported_hardware.inc.md。310p 这一标识贯穿了本文后续的所有环节:官方 CANN 基础镜像 tag、官方预构建 vLLM Ascend 镜像 tag、手动构建所用 Dockerfile(Dockerfile.310p、Dockerfile.310p.openEuler)以及容器内安装软件时的特殊处理。
310p 硬件路径的关键差异
与 A2 / A3 / 950DT 不同,Atlas 300I DUO / Atlas 200I Pro 不支持 triton 与 triton-ascend。仓库安装文档 install_vllm_ascend.inc.md 中明确指出,若环境中已存在这两个包,需要先卸载且不要重装:
pip uninstall -y triton triton-ascend
同理,官方预构建镜像中,A2、A3、950DT 镜像内置了对应的 Triton Ascend 运行时,而 Atlas 300I DUO 与 Atlas 200I Pro 镜像不使用 Triton Ascend(见 quick_start.md 的软件栈说明)。因此本文的容器环境搭建与推理示例均围绕这一差异展开。
二、两种安装路径与本文定位
仓库的 安装指南 提供了三种环境搭建路径,本文聚焦其中与 Atlas 300I DUO 强相关的 CANN 环境路径:
- 预构建镜像(Prebuilt image):直接拉取官方
quay.io/ascend/vllm-ascend:*镜像,容器内已包含 CANN、NNAL、PyTorch、TorchNPU、vLLM 与 vLLM Ascend 全套软件栈(见 prebuilt_image.inc.md),适合追求最快上手的用户。 - CANN 环境(本文主题):以官方 CANN 基础镜像为底座(或复用宿主机/既有容器中的 CANN 安装),再自行安装 vLLM 与 vLLM Ascend,适合需要精确控制软件栈版本的用户(见 existing_cann_environment.inc.md)。
- 基础环境(Base environment):从零在 Linux 主机或最小容器中手工安装 CANN Toolkit、Ops 与 NNAL,面向高级用户(见 base_environment.inc.md)。
CANN 基础镜像的优势在于:镜像内已包含 Toolkit、目标硬件对应的算子包(Ops)以及 NNAL,容器内无需重新安装 CANN,只需按本文命令启动容器并安装 vLLM / vLLM Ascend 即可。
版本说明
当前文档栈对应的版本可在仓库根目录配置文件 mkdocs.yml 中查到:CANN 为 9.1.0(模板变量 release_cann_version),vLLM Ascend 为 v0.23.0(模板变量 vllm_ascend_version),PyTorch 为 2.10.0,TorchNPU 为 2.10.0.post4。文中出现的 9.1.0 即该模板变量的渲染值,实际使用时请以目标发布版本对应的文档为准。
三、拉取 Atlas 300I DUO 的 CANN 镜像
在启动容器之前,先从 quay.io 拉取与硬件、操作系统匹配的官方 CANN 基础镜像。仓库文档 atlas-300i-duo.inc.md 给出了 Ubuntu 与 openEuler 两种系统下的拉取命令。
Ubuntu 系统
export IMAGE=quay.io/ascend/cann:9.1.0-310p-ubuntu22.04-py3.12
docker pull "$IMAGE"
openEuler 系统
export IMAGE=quay.io/ascend/cann:9.1.0-310p-openeuler24.03-py3.12
docker pull "$IMAGE"
对镜像 tag 的解读(9.1.0-310p-ubuntu22.04-py3.12):
9.1.0:CANN 发布版本;310p:面向 Atlas 300I DUO / Atlas 200I Pro 的硬件构建标识;ubuntu22.04/openeuler24.03:基础操作系统;py3.12:容器内 Python 版本(官方镜像统一使用 Python 3.12,见 mkdocs.yml 中的release_image_python_version)。
四、启动容器:参数逐项解析
拉取完成后,即可启动容器。Ubuntu 与 openEuler 的启动命令完全一致(仅 $IMAGE 指向不同镜像)。以下为 Ubuntu 下的完整命令:
export DEVICE=/dev/davinci0
export MODEL_CACHE="${HOME}/.cache"
mkdir -p "$MODEL_CACHE"
docker run --rm \
--name vllm-ascend-cann \
--shm-size=1g \
--device "$DEVICE" \
--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 /etc/ascend_install.info:/etc/ascend_install.info \
-v "$MODEL_CACHE:/root/.cache" \
-p 8000:8000 \
-it "$IMAGE" bash
设备透传参数(--device)
昇腾 NPU 在容器内访问依赖多个内核设备节点,每个参数都有明确用途:
| 参数 | 作用 |
|---|---|
--device /dev/davinci0 |
透传第 0 张昇腾推理卡(Atlas 300I DUO),多卡场景可追加 davinci1、davinci2 等 |
--device /dev/davinci_manager |
透传 Davinci 设备管理节点,负责设备注册与任务调度 |
--device /dev/devmm_svm |
透传共享虚拟内存(Shared Virtual Memory)管理节点 |
--device /dev/hisi_hdc |
透传 Host Device Communication(HDC)通道节点,用于主机与设备间通信 |
这些设备节点是容器内驱动访问的必经通道,缺少任何一个都可能导致 torch.npu 无法检测到设备。
目录挂载参数(-v)
| 挂载项 | 作用 |
|---|---|
/usr/local/dcmi |
DCMI(Device Control Management Interface)库,npu-smi 等管理工具依赖 |
/usr/local/bin/npu-smi |
将宿主机 npu-smi 工具带入容器,便于容器内查询设备状态 |
/usr/local/Ascend/driver/lib64/ |
昇腾驱动用户态库,容器内 CANN 运行时的依赖 |
/usr/local/Ascend/driver/version.info |
驱动版本信息文件,CANN 校验驱动版本时读取 |
/etc/ascend_install.info |
昇腾软件安装信息(安装路径、用户等),CANN 环境初始化依据 |
$MODEL_CACHE:/root/.cache |
模型下载缓存目录映射,避免每次启动容器重复下载 Hugging Face / ModelScope 模型 |
其中 MODEL_CACHE 通过 export MODEL_CACHE="${HOME}/.cache" 指向宿主机家目录下的 .cache,并用 mkdir -p 预创建,这样容器内 /root/.cache 的模型缓存可以持久化到宿主机。
其他关键参数
--shm-size=1g:将容器共享内存设为 1 GB。PyTorch DataLoader 多进程、vLLM 引擎与调度进程间的张量共享都依赖/dev/shm,容量过小会触发"no space left on device"类错误。-p 8000:8000:映射 vLLM OpenAI 兼容 API 端口。在线服务默认监听 8000 端口,后续curl http://localhost:8000/v1/models即通过该映射访问。--rm:容器退出后自动删除文件系统层,配合MODEL_CACHE挂载保证模型缓存不丢失。-it "$IMAGE" bash:以交互式终端进入容器 bash,后续所有安装与推理操作都在容器内执行。
openEuler 系统下只需将 IMAGE 指向 ...-310p-openeuler24.03-py3.12 镜像,其余参数完全一致(命令原文见 atlas-300i-duo.inc.md)。
五、验证容器内的 NPU 环境
进入容器后,先验证环境是否就绪。仓库文档 verify_container.inc.md 给出的判定标准是:输出包含 vLLM Ascend environment: OK。
npu-smi info
python3 - <<'PY'
import torch
import vllm
import vllm_ascend
assert torch.npu.is_available(), "No available Ascend NPU detected in the container"
print("vLLM Ascend environment: OK")
PY
npu-smi info输出设备列表、芯片温度与算力状态,确认设备节点透传成功;- Python 片段依次导入
torch、vllm、vllm_ascend,并通过torch.npu.is_available()断言 NPU 在容器内可见。注意:此时容器内还未安装 vllm 与 vllm_ascend,导入会失败属正常现象——该验证脚本在"预构建镜像"路径下直接可用,而在 CANN 基础镜像路径下,请先完成下一节的安装步骤。
六、在容器内安装 vLLM 与 vLLM Ascend
CANN 基础镜像只含 CANN 用户态环境,vLLM 与 vLLM Ascend 需要自行安装。仓库文档 install_vllm_ascend.inc.md 给出了 pip、uv(WheelNext)与源码三种方式,并明确 pip 方式目前只支持 A2 构建,无法自动适配 Atlas 300I DUO / Atlas 200I Pro / A3 / 950DT。因此 310p 硬件推荐使用 uv(WheelNext)或源码安装。
准备系统依赖(容器内)
Ubuntu 容器:
sed -i 's|ports.ubuntu.com|mirrors.tuna.tsinghua.edu.cn|g' /etc/apt/sources.list
apt-get update -y && apt-get install -y gcc g++ cmake ninja-build libnuma-dev wget git curl jq
pip config set global.index-url "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple"
openEuler 容器:
yum update -y && yum install -y gcc g++ cmake ninja-build numactl-devel wget git curl jq patch
pip config set global.index-url "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple"
方式一:uv + WheelNext(推荐)
WheelNext 会根据检测到的硬件从变体索引中选择匹配的 vLLM Ascend wheel,正好解决 310p 硬件无标准 pip wheel 的问题:
# 安装 uv-wheelnext
curl -LsSf https://astral.sh/uv/install.sh | sed 's/verify_checksum "$_file"/true/' | INSTALLER_DOWNLOAD_URL=https://wheelnext.astral.sh sh
source $HOME/.local/bin/env
# 安装 vllm(当前文档栈支持的最新版本为 v0.23.0)
pip install "vllm==0.23.0"
# 从 wheelnext 索引安装 vllm-ascend
uv pip install --system \
--extra-index-url https://mirrors.huaweicloud.com/ascend/repos/pypi/variant \
--index-url https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple \
--find-links https://mirrors.huaweicloud.com/ascend/repos/pypi/triton-ascend/ \
"vllm-ascend==0.23.0"
安装失败时可先清空 uv 缓存后重试:
uv cache clean
安装后可打印 wheel 对应的设备类型,确认得到的是 310p 构建:
python - <<'PY'
from vllm_ascend._build_info import __device_type__
print("vLLM Ascend wheel device type:", __device_type__)
PY
方式二:源码安装
# 安装 vLLM
git clone --depth 1 --branch v0.23.0 https://github.com/vllm-project/vllm
cd vllm
VLLM_TARGET_DEVICE=empty pip install -e . \
--extra-index-url https://download.pytorch.org/whl/cpu/
cd ..
# 安装 vLLM Ascend
git clone --depth 1 --branch v0.23.0 https://github.com/vllm-project/vllm-ascend.git
cd vllm-ascend
pip install -e . \
--extra-index-url https://download.pytorch.org/whl/cpu/ \
--extra-index-url https://mirrors.huaweicloud.com/ascend/repos/pypi
cd ..
310p 特例:不安装 triton / triton-ascend
无论采用哪种方式,安装完成后都需确认容器内没有 triton 与 triton-ascend:
pip uninstall -y triton triton-ascend
完成安装后回到上一节的验证脚本,输出 vLLM Ascend environment: OK 即代表环境就绪。
七、Atlas 300I DUO 的推理运行约束与实战
310p 硬件在 vLLM 图编译与量化上有明确的运行时约束,仓库在 离线推理示例 与 在线服务示例 中给出了已在 Atlas 300I DUO / Atlas 200I Pro 上验证过的三条硬性要求:
- 必须使用
float16精度; - 必须使用
FULL_DECODE_ONLY图捕获模式,并限制图捕获规模(cudagraph_capture_sizes); - 不支持
enable_npugraph_ex,必须显式关闭:--additional-config '{"ascend_compilation_config": {"enable_npugraph_ex":false}}'。
离线推理(Offline Inference)
在容器终端创建 example.py:
from vllm import LLM, SamplingParams
MODEL = "Qwen/Qwen3-0.6B"
prompts = [
"Hello, my name is",
"The future of AI is",
]
llm = LLM(
model=MODEL,
dtype="float16",
max_num_seqs=8,
compilation_config={
"cudagraph_mode": "FULL_DECODE_ONLY",
"cudagraph_capture_sizes": [1, 2, 4, 8],
},
additional_config={
"ascend_compilation_config": {
"enable_npugraph_ex": False,
},
},
)
sampling_params = SamplingParams(
temperature=0.0,
max_tokens=32,
)
outputs = llm.generate(prompts, sampling_params)
assert len(outputs) == len(prompts)
for output in outputs:
generated_text = output.outputs[0].text
assert generated_text.strip()
print(f"Prompt: {output.prompt!r}, Generated text: {generated_text!r}")
运行:
python3 example.py
启动日志中应能看到 Ascend 平台插件被激活:
INFO 05-27 11:40:38 [__init__.py:44] Available plugins for group vllm.platform_plugins:
INFO 05-27 11:40:38 [__init__.py:46] - ascend -> vllm_ascend:register
INFO 05-27 11:40:38 [__init__.py:49] All plugins in this group will be loaded. Set `VLLM_PLUGINS` to control which plugins to load.
INFO 05-27 11:40:38 [__init__.py:238] Platform plugin ascend is activated
max_num_seqs=8 与 cudagraph_capture_sizes=[1, 2, 4, 8] 相呼应:捕获规模不超过最大并发序列数,避免无效的图捕获。示例结束后出现的 EngineCore shutdown 日志与 DeprecationWarning 不影响推理结果,属正常退出信息。
在线服务(Online Serving)
后台启动 OpenAI 兼容服务:
vllm serve Qwen/Qwen3-0.6B \
--dtype float16 \
--max-num-seqs 8 \
--compilation-config '{"cudagraph_mode":"FULL_DECODE_ONLY","cudagraph_capture_sizes":[1,2,4,8]}' \
--additional-config '{"ascend_compilation_config":{"enable_npugraph_ex":false}}' &
看到以下日志即服务启动成功:
INFO: Started server process [3594]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
查询模型列表:
curl --fail http://localhost:8000/v1/models
发送补全请求:
curl --fail http://localhost:8000/v1/completions \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen/Qwen3-0.6B",
"prompt": "Beijing is a",
"max_tokens": 5,
"temperature": 0
}'
确认响应中 choices[0].text 包含非空生成文本才算推理成功——报错响应或空补全都不能证明推理可用。
优雅停止服务(等价于前台进程按 Ctrl+C):
VLLM_PID=$(pgrep -f "vllm serve")
kill -2 "$VLLM_PID"
注意:执行前请确认
VLLM_PID指向本示例启动的服务,避免误杀环境中其他vllm serve进程。停止后可执行Ctrl+D退出容器。
八、其他相关路径速览
使用预构建镜像(最快路径)
若希望跳过安装步骤,直接使用官方预构建镜像 atlas-300i-duo.inc.md(位于 quick_start 目录),拉取命令为:
# Ubuntu
export IMAGE=quay.io/ascend/vllm-ascend:v0.23.0-310p
docker pull "$IMAGE"
# openEuler
export IMAGE=quay.io/ascend/vllm-ascend:v0.23.0-310p-openeuler
docker pull "$IMAGE"
容器启动参数与本文第四节一致(镜像内置完整软件栈,验证脚本直接通过),完整步骤见 prebuilt_image.inc.md。该镜像与官方 CANN 基础镜像不同:前者 tag 前缀为 quay.io/ascend/vllm-ascend:,后者为 quay.io/ascend/cann:,使用时不要混淆。
手动构建 310p 镜像
需要定制镜像时可从源码构建,Ubuntu 与 openEuler 分别使用 Dockerfile.310p 与 Dockerfile.310p.openEuler:
git clone --depth 1 --branch v0.23.0 \
https://github.com/vllm-project/vllm-ascend.git
cd vllm-ascend
# Ubuntu
docker build -t vllm-ascend-dev:latest -f Dockerfile.310p .
# openEuler
docker build -t vllm-ascend-dev:latest -f Dockerfile.310p.openEuler .
复用宿主机已有的 CANN 安装
若宿主机或既有容器已装好 CANN,可跳过镜像拉取,直接配置环境变量后安装 vLLM Ascend(详见 existing_cann_environment.inc.md):
source /usr/local/Ascend/ascend-toolkit/set_env.sh
if [ -f /usr/local/Ascend/nnal/atb/set_env.sh ]; then
source /usr/local/Ascend/nnal/atb/set_env.sh
fi
export ASCEND_TOOLKIT_HOME="${ASCEND_TOOLKIT_HOME:-/usr/local/Ascend/ascend-toolkit/latest}"
npu-smi info
该路径要求确认 /usr/local/Ascend/nnal/atb/set_env.sh 与 libatb.so(NNAL 的 ATB 算子库)可用;若运行时出现 libatb.so not found,说明 NNAL 安装不完整,需回查安装步骤。
九、常见问题与排障要点
- 容器内检测不到 NPU:优先检查设备透传参数是否完整(
davinci0、davinci_manager、devmm_svm、hisi_hdc),再确认驱动目录挂载(/usr/local/Ascend/driver/lib64/、version.info)与/etc/ascend_install.info是否存在。 libatb.so not found:NNAL 环境未就绪,确认set_env.sh已 source 且libatb.so路径可访问。- pip 安装 vllm-ascend 后设备类型不是 310p:pip 预构建 wheel 目前仅覆盖 A2,310p 硬件必须改用 uv(WheelNext)或源码安装。
- 图捕获报错或服务启动失败:核对
--dtype float16、FULL_DECODE_ONLY、cudagraph_capture_sizes不超过max-num-seqs,并确认enable_npugraph_ex已显式关闭。 - 模型下载失败:若 Hugging Face 访问受限,可设置
export VLLM_USE_MODELSCOPE=True并安装modelscope,或将已下载的模型目录直接替换示例中的模型 ID。
十、总结
在 Atlas 300I DUO 上运行 vLLM Ascend 的核心链路可概括为:拉取 310p 版 CANN 镜像 → 透传 NPU 设备与驱动挂载启动容器 → 通过 uv 或源码安装 vLLM / vLLM Ascend → 卸载 triton 系包 → 以 float16 + FULL_DECODE_ONLY + 关闭 npugraph_ex 的约束组合运行推理。本文涉及的全部命令与参数均可在仓库 installation 目录 与 quick_start 目录 找到原文依据;完整的离线/在线推理示例、验证脚本与预构建镜像路径,也请以这些文档的最新版本为准。