华为 Atlas 300V 兼容性测试报告
测试结论:PASS ------ 华为 Atlas 300V 视频解析卡在本文所述的 PVE 虚拟化环境中功能完整、运行稳定,全部 8 项测试用例通过,宿主侧 PCIe 错误计数归零。
| 项 | 值 |
|---|---|
| 报告日期 | 2026-10-20 |
| 报告版本 | v1.0 |
| 测试对象 | 华为 Atlas 300V 视频解析卡(PCIe 19e5:d500,芯片 Ascend 310P3,板载 24GB LPDDR4X) |
| 测试形态 | 整机 PCIe 直通(PVE 宿主 → KVM 虚拟机,非 SR-IOV、非 vNPU 切分) |
| 宿主平台 | PVE 9.2.3 / Debian 13.5 / 内核 7.0.6-2-pve / Intel C621 / Xeon Scalable Gen1/2 / 62GB RAM |
| 客户端 OS | Ubuntu 20.04 (focal) / 内核 5.15.0-139-generic / 32GB / 48 vCPU |
| 软件栈 | Ascend 驱动 25.5.2 + 固件 7.8.0.7.220 + CANN 8.5.2(toolkit / ops / nnal) |
| 被测程序 | AscendDemo(C++ / ACL,含 Python 扩展) |
| 关联文档 | 透传实施记录、固件修复实施记录 |
0. 摘要
本次测试的目标是回答一个问题:Atlas 300V 这张卡,在"物理机装 Hypervisor、卡整体直通给一台 Linux 虚拟机"这种形态下,能不能正常用?
结论是能。但过程中踩到了 5 个真实的坑,其中 2 个是华为官方文档没有明说、或者文档说了但容易被误读的地方:
- 固件包必须单独安装 ------驱动包
.run --full不含固件,漏装不会报错,而是让设备永远等不到 ready,最终由卡自己中止 PCIe 事务把虚拟机打崩。 - "固件不支持在虚拟机安装"这个限制在直通场景下不触发 ------它的实现是安装器里的一个退出码判断,直通时驱动把卡认作物理机,因此可以直接在虚拟机里刷固件。
本报告第 5 章完整记录了这 5 个坑的现象、根因与解法,照着第 3 章的步骤 + 第 5 章的坑位,可以在任意一台同规格机器上复现全部结果。
测试结果总览
| 编号 | 测试项 | 判定 | 关键实测结果 |
|---|---|---|---|
| T1 | 设备识别 | ✅ PASS | npu-smi info 识别 310P3 ,Health OK,显存 1858/21525 MB |
| T2 | 固件版本一致性 | ✅ PASS | 卡上 hboot1a/b、hlink = 7.8.0.7.220,与驱动 25.5.2 配套 |
| T3 | 单元测试 | ✅ PASS | ctest 4/4 通过(letterbox / output / fp16 / cpu_preprocess) |
| T4 | 单帧图像推理 | ✅ PASS | 3 个检测框:person 91.11%、helmet 81.10%、no_helmet 76.12% |
| T5 | 视频流水线推理 | ✅ PASS | 75 帧全流程跑通,平均推理 0.14 ms/帧,输出可视化视频 |
| T6 | Python 扩展模块 | ✅ PASS | AscendInfer.cpython-38-x86_64-linux-gnu.so 导入正常 |
| T7 | PCIe 链路稳定性 | ✅ PASS | 宿主 AER 错误累计 1 次(修复前) ,测试全程零新增 |
| T8 | AICore 算力加载 | ✅ PASS | 重负载下 Aicore Usage Rate 0% → 3% 实时抬升 |
1. 测试目的与范围
1.1 目的
验证 Atlas 300V 在虚拟化直通形态下的可用性,覆盖以下五个方面:
- 设备能否被虚拟机内的驱动正常识别与初始化
- 驱动 / 固件 / CANN 三层软件栈能否正确配套并协同工作
- 真实推理程序能否编译、加载模型、下发任务并拿到正确结果
- 高负载下 PCIe 链路是否稳定(不出现 AER / 链路重置)
- 算术任务是否真的由 NPU 加速单元执行,而非退化为 Host 侧执行
1.2 范围
| 覆盖 | 内容 |
|---|---|
| ✅ 覆盖 | 设备枚举、驱动加载、固件刷写、CANN 运行时、模型转换(atc)、C++ 推理、Python 扩展、PCIe 稳定性、AICore 负载验证 |
| ⚠️ 部分覆盖 | 性能基线------因缺少可用的真模型(YOLO 权重导出链路未打通,见 §7),性能数据仅以合成模型给出趋势性结论,不作为绝对算力基线 |
| ❌ 不覆盖 | DVPP 硬编解码性能对照(demo 走的是 CPU 预处理回退路径,见 §7)、多卡/多 VM 共享、vNPU 切分、裸金属对比 |
2. 测试环境
2.1 硬件环境
| 角色 | 型号 / 参数 |
|---|---|
| 被测卡 | 华为 Atlas 300V 视频解析卡 |
| 宿主主板 | G2DEW-B(板号 1.21.222.0353,板卡 Mfg Date 2023-09-25) |
| 芯片组 | Intel C621 |
| BIOS | AMI 5.14 (2021-01-26) |
| CPU | Intel Xeon Scalable Gen1/2(Skylake-SP / Cascade Lake) |
| 内存 | 62 GB(测试期已用 38 GB / 可用 24 GB) |
| 宿主存储 | local-lvm,VM 101 虚拟磁盘 256 GB |
| 网络 | VM 101 → virtio 网卡 → vmbr0,静态 IP 192.168.0.93 |
2.2 Atlas 300V 卡片信息
| 项 | 值 |
|---|---|
| PCI 地址(宿主) | 0000:18:00.0 |
| Vendor / Device | 19e5:d500(Huawei) |
| Subsystem | 0200:0100 |
| Class | 0x120000 Processing accelerators |
| 芯片 | Ascend 310P3 ,Chip Version V1,Board ID 0x6e |
| 板载内存 | 24 GB LPDDR4X(npu-smi 报 DDR 21525 MB 可用) |
| BAR0 | aa000000,64-bit non-prefetchable,8 MB(控制寄存器) |
| BAR2 | 387ff8000000,64-bit prefetchable,128 MB(PCIe 侧数据窗口) |
| MSI-X | 512 vectors |
| PCIe 链路 | 协商 8 GT/s x16 (capable 16 GT/s Gen4)------受宿主上游 root port 0000:17:00.0(Intel Sky Lake-E 8086:2030)限制,硬件上限 |
| 上游 root port | 0000:17:00.0 |
| IOMMU group | 6,单例 (仅含 0000:18:00.0)------透传理想条件,无需 ACS 绕过 / pcie_acs_override |
| SPI Flash | Macronix 16 MB(Manufacturer ID 0xC2,Flash Count 1) |
2.3 虚拟化拓扑
PVE 宿主 (192.168.0.144) Ubuntu 20.04 VM 101 (192.168.0.93)
├─ 内核 7.0.6-2-pve ├─ 内核 5.15.0-139-generic
├─ intel_iommu=on iommu=pt ├─ 48 vCPU / 32 GB / local-lvm 256GB
├─ IOMMU group 6 (单例) ├─ Ascend 驱动 25.5.2 + 固件 7.8.0.7.220
│ └─ 0000:18:00.0 Atlas 300V ├─ CANN 8.5.2 (toolkit/ops/nnal)
│ │ vfio-pci 绑定 └─ AscendDemo (ACL C++ + Python)
│ └─── PCI 透传 ──► 0000:01:00.0 (devid 0, NPU ID 256)
└─ 宿主侧 AER 计数:1(修复前 1 次,测试期零新增)
宿主侧 IOMMU 状态(实测):
$ cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-7.0.6-2-pve ... quiet intel_iommu=on iommu=pt crashkernel=512M
$ dmesg | grep -i "Default domain type"
[ 1.154696] iommu: Default domain type: Passthrough (set via kernel command line)
$ ls /sys/kernel/iommu_groups/6/devices/
0000:18:00.0
$ lspci -k -s 18:00.0
18:00.0 Processing accelerators: Huawei Technologies Co., Ltd. Device d500 (rev 23)
Subsystem: Dell (wrong ID) Device 0100
Kernel driver in use: vfio-pci
2.4 软件版本矩阵
三层必须严格配套,本次选用如下组合(依据 CANN 8.5.2 与驱动的官方兼容区间):
| 层 | 组件 | 版本 | 配套性依据 |
|---|---|---|---|
| 运行时 | Ascend-cann-toolkit | 8.5.2 | 被 AscendDemo/CMakeLists.txt:78 硬编码锁定为 /usr/local/Ascend/cann-8.5.2/x86_64-linux/devlib |
| 运行时 | Ascend-cann-310p-ops | 8.5.2 | 与 toolkit 同版本 |
| 运行时 | Ascend-cann-nnal | 8.5.2 | 必须排在 toolkit 之后安装 |
| 驱动 | Ascend-hdk-310p-npu-driver | 25.5.2 | 固件包声明 compatible_version_drv=[..., 25.0, 25.5.] |
| 固件 | Ascend-hdk-310p-npu-firmware | 7.8.0.7.220 | 驱动声明 compatible_version_fw=[6.4.0,6.4.99],[7.0.0,8.9.9] |
安装包完整性:5 个 .run 全部通过 --version 自证,并逐个校验 SHA256 通过。
客户端系统包版本(实测):
| 包 | 版本 | 用途 |
|---|---|---|
| build-essential | 12.8ubuntu1.1(gcc 9.4.0) | 驱动 DKMS 编译 / C++ 编译 |
| cmake | 3.16.3 | 构建 AscendDemo |
| libopencv-dev | 4.2.0+dfsg-5 | 视频解码 / 预处理 / 可视化 |
| nlohmann-json3-dev | 3.7.3 | 配置解析 |
| libgtest-dev | 1.10.0-2 | 单元测试框架 |
| ffmpeg + libavcodec-dev | 4.2.7 | 测试视频生成 |
| python3-dev / python3-pip | 3.8.2 / 20.0.2 | Python 扩展模块编译 |
Python 环境(按"开发用 uv venv / 工具链用系统 Python"的分离原则):
| 环境 | Python | 关键包 |
|---|---|---|
项目 venv(.venv) |
3.8.10 | numpy 1.24.4、onnx 1.17.0、onnxruntime 1.19.2、opencv-python-headless 4.10.0.84、torch 2.4.1+cpu |
| 系统 python3(atc 用) | 3.8.10 | numpy 1.24.4、protobuf 3.6.1、attrs、psutil、PyYAML、cffi、Pillow、sympy、scipy、requests、absl-py、decorator 5.3.1 |
decorator是 CANNatc的硬依赖,缺失时 atc 会报Environment_Error_Import_Python_Module_Failed(EC0010): No module named 'decorator'。
3. 安装部署步骤(可复现)
以下命令均以普通用户在 VM 内执行,需要 root 权限处加
sudo。SSH 提示 host key 问题时可用
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=NUL <user>@<ip>。
3.0 前置准备
下载并上传 5 个安装包到 VM 的 /home/hybors/atlas300v/:
Ascend-hdk-310p-npu-driver_25.5.2_linux-x86-64.run
Ascend-hdk-310p-npu-firmware_7.8.0.7.220.run
Ascend-cann-toolkit_8.5.2_linux-x86-64.run
Ascend-cann-310p-ops_8.5.2_linux-x86-64.run
Ascend-cann-nnal_8.5.2_linux-x86-64.run
逐个自证版本(避免拿到错包):
bash
cd /home/hybors/atlas300v
for f in *.run; do echo "--- $f"; ./$f --version 2>&1 | grep -E "Verifying|SHA256|Version" | head -3; done
3.1 宿主侧:把卡交给 vfio-pci
bash
# PVE 宿主 (root)
cat > /etc/modprobe.d/vfio.conf <<'EOF'
options vfio-pci ids=10de:2204,10de:1aef,19e5:d500 disable_vga=1
EOF
update-initramfs -u -k all
reboot
验证绑定:
bash
lspci -k -s 18:00.0 | grep "Kernel driver" # → Kernel driver in use: vfio-pci
ls /sys/kernel/iommu_groups/6/devices/ # → 0000:18:00.0(单例)
3.2 客户端 OS 基础环境
换 apt 源 。默认源缺少 focal-updates / focal-security,会导致 OpenCV 依赖链断掉(libgphoto2-6 只有 dev 2.5.24 而需求 2.5.25):
bash
sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak-ascend
sudo tee /etc/apt/sources.list > /dev/null <<'EOF'
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal main restricted
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal universe
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-updates main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-security main restricted universe multiverse
EOF
sudo apt update
装系统包:
bash
sudo apt install -y build-essential cmake git pkg-config \
libopencv-dev nlohmann-json3-dev libgtest-dev \
python3-dev python3-pip ffmpeg libavcodec-dev
创建驱动安装硬性要求的运行用户(安装器会以 0x0091 拒绝没有该用户的环境):
bash
sudo groupadd -f HwHiAiUser
sudo useradd -g HwHiAiUser -d /home/HwHiAiUser -m -s /bin/bash HwHiAiUser
预留大页(可选,驱动在分配大块连续内存时会用到):
bash
echo 'vm.nr_hugepages = 2048' | sudo tee /etc/sysctl.d/99-ascend-hugepages.conf
sudo sysctl --system
3.3 安装 Ascend 驱动(25.5.2)
⚠️ 本步骤含一个内核兼容性 workaround,详见 §5.1。 在 5.15 内核上直接安装会 DKMS 编译失败。
(可选但推荐)预置内核头补丁:
bash
for V in 139 46; do
F=/usr/src/linux-headers-5.15.0-${V}-generic/include/linux/bits.h
sudo cp -n "$F" "$F.orig-ascend"
sudo sed -i 's/(l) > (h)/(long)(l) > (long)(h)/g' "$F"
done
该模式在
bits.h中只出现在第 25 行 (一处行内两处),替换范围唯一,不影响其他宏。实际改动是把
GENMASK_INPUT_CHECK里的(l) > (h)改成(long)(l) > (long)(h),消除有符号/无符号比较告警,断言语义保持不变。补丁后:
c
/* 补丁前 */
#define GENMASK_INPUT_CHECK(h, l) \
(BUILD_BUG_ON_ZERO(__builtin_choose_expr( \
__is_constexpr((l) > (h)), (l) > (h), 0)))
/* 补丁后 */
#define GENMASK_INPUT_CHECK(h, l) \
(BUILD_BUG_ON_ZERO(__builtin_choose_expr( \
__is_constexpr((long)(l) > (long)(h)), (long)(l) > (long)(h), 0)))
安装驱动:
bash
cd /home/hybors/atlas300v
sudo ./Ascend-hdk-310p-npu-driver_25.5.2_linux-x86-64.run --full
重启使驱动生效:
bash
sudo reboot
3.4 安装配套固件(7.8.0.7.220)★ 关键步骤
这是最容易漏掉的一步。驱动装完不算装完,没有配套固件,设备永远等不到 ready,第一次推理就会把虚拟机打崩(现象见 §5.2)。
bash
cd /home/hybors/atlas300v
sudo ./Ascend-hdk-310p-npu-firmware_7.8.0.7.220.run --full --quiet
预期输出:
[Firmware] [INFO]upgradePercentage: 0% → 90% → 100%
[Firmware] [INFO]The firmware of [1] chips are successfully upgraded.
[Firmware] [INFO]Firmware package installed successfully! Reboot now or after driver installation ...
必须重启虚拟机,固件才生效:
bash
# PVE 宿主
qm shutdown 101 --timeout 90
qm start 101
验证固件真的落到卡上(版本号应从出厂旧版变成 7.8.0.7.220):
bash
sudo /usr/local/Ascend/driver/tools/upgrade-tool --device_index -1 --component -1 --version
3.5 安装 CANN 8.5.2
顺序固定:toolkit → ops → nnal 。安装器默认要交互接受 EULA,用 --quiet 免交互。
bash
cd /home/hybors/atlas300v
yes | sudo ./Ascend-cann-toolkit_8.5.2_linux-x86-64.run --install
yes | sudo ./Ascend-cann-310p-ops_8.5.2_linux-x86-64.run --install
# nnal 依赖 toolkit 的环境变量,必须带全套 env 重装
source /usr/local/Ascend/ascend-toolkit/set_env.sh
yes | sudo env "ASCEND_TOOLKIT_HOME=$ASCEND_TOOLKIT_HOME" \
"ASCEND_NNAE_HOME=$ASCEND_NNAE_HOME" \
"ASCEND_HOME_PATH=$ASCEND_HOME_PATH" \
"ASCEND_OPP_PATH=$ASCEND_OPP_PATH" \
"ASCEND_AICPU_PATH=$ASCEND_AICPU_PATH" \
"TOOLCHAIN_HOME=$TOOLCHAIN_HOME" \
./Ascend-cann-nnal_8.5.2_linux-x86-64.run --install
验证关键路径:
bash
ls /usr/local/Ascend/cann-8.5.2/set_env.sh
ls /usr/local/Ascend/ascend-toolkit/set_env.sh
ls /usr/local/Ascend/cann-8.5.2/x86_64-linux/devlib/libascend_hal.so
3.6 Python 环境
项目 venv(开发用):
bash
# uv 0.13.3(GitHub 不可达时从清华 PyPI 装)
uv venv --python /usr/bin/python3 /home/hybors/atlas300v/AscendDemo/.venv
uv pip install --python /home/hybors/atlas300v/AscendDemo/.venv/bin/python \
numpy==1.24.4 onnx==1.17.0 onnxruntime==1.19.2 \
opencv-python-headless==4.10.0.84 torch==2.4.1
opencv-python-headless固定在 4.10.0.84,不要用 5.x:需与 C++ 侧的 libopencv 4.2.0 行为对齐。
系统 python3(atc 工具链用):
bash
sudo pip3 install "numpy<1.25" "protobuf<3.21" attrs psutil pyyaml cffi \
pillow sympy scipy requests absl-py decorator
⚠️ atc 必须在系统 python 下跑 。若当前 shell 激活了 uv venv,atc 会用 venv 的 python,报
No module named 'decorator'。转换前先deactivate或开新会话。
3.7 编译 AscendDemo
bash
cd /home/hybors/atlas300v/AscendDemo
source /usr/local/Ascend/ascend-toolkit/set_env.sh
cmake -S . -B build \
-DASCEND_ENABLED=ON \
-DASCEND_DIR=/usr/local/Ascend/ascend-toolkit/latest \
-DPython3_EXECUTABLE=/home/hybors/atlas300v/AscendDemo/.venv/bin/python
cmake --build build -j$(nproc)
cd build && ctest --output-on-failure
ctest --test-dir需要 CMake ≥ 3.20,本机 3.16 必须先cd build再ctest。
3.8 准备测试模型
bash
cd /home/hybors/atlas300v/test_assets
atc --model=test_model.onnx --framework=5 --output=test_model \
--soc_version=Ascend310P3 --input_shape="image:1,3,544,960" \
--input_format=NCHW --log=info
⚠️
--framework必须是 5 (ONNX)。CANN 8.5.2 只接受 0/1/3/5,--framework=10会直接报错。
测试素材(合成模型 + 640x480/25fps/75 帧测试视频 + 单帧图片)放在 /home/hybors/atlas300v/test_assets/。
4. 测试用例与结果
T1|设备识别 ✅ PASS
步骤
bash
sg HwHiAiUser -c "npu-smi info"
sg HwHiAiUser -c "npu-smi info -t board -i 256 -c 0"
实测输出
+--------------------------------------------------------------------------------------------------------+
| npu-smi 25.5.2 Version: 25.5.2 |
+-------------------------------+-----------------+------------------------------------------------------+
| NPU Name | Health | Power(W) Temp(C) Hugepages-Usage(page) |
| Chip Device | Bus-Id | AICore(%) Memory-Usage(MB) |
+===============================+=================+======================================================+
| 256 310P3 | OK | NA 32 0 / 0 |
| 0 0 | 0000:01:00.0 | 0 1858 / 21525 |
+-------------------------------+-----------------+------------------------------------------------------+
板级信息:
NPU ID : 256
Chip ID : 0
Chip Type : Ascend
Chip Name : 310P3
Chip Version : V1
Board ID : 0x6e
PCIe Bus Info : 0000:01:00.0
判定:卡被正常枚举为 310P3,Health = OK,显存 1858/21525 MB,温度可读(32~41 ℃ 随负载变化)。✔
T2|固件版本一致性 ✅ PASS
步骤
bash
sudo /usr/local/Ascend/driver/tools/upgrade-tool --device_index -1 --component -1 --version
实测输出
{
Get component version(7.8.0.7.220) succeed for deviceId(0), componentType(11).
{"device_id":0, "component":hboot1a, "version":7.8.0.7.220}
Get component version(7.8.0.7.220) succeed for deviceId(0), componentType(12).
{"device_id":0, "component":hboot1b, "version":7.8.0.7.220}
Get component version(7.8.0.7.220) succeed for deviceId(0), componentType(18).
{"device_id":0, "component":hlink, "version":7.8.0.7.220}
}
判定 :卡上固件为 7.8.0.7.220,与驱动 25.5.2、CANN 8.5.2 三方配套一致。✔
已知读数异常(不影响功能) :
npu-smi info -t board的Firmware Version字段在本环境中恒为NA,而upgrade-tool能正确读出 7.8.0.7.220。说明该字段在 vfio 直通下的读取路径受限,不能作为"固件是否安装成功"的判据 ------请以upgrade-tool --component -1 --version为准。
T3|单元测试 ✅ PASS
步骤 :cd build && ctest --output-on-failure
实测输出
Start 1: letterbox
1/4 Test #1: letterbox ......................... Passed
Start 2: output
2/4 Test #2: output ............................ Passed
Start 3: fp16
3/4 Test #3: fp16 ............................. Passed
Start 4: cpu_preprocess
4/4 Test #4: cpu_preprocess ................... Passed
100% tests passed, 0 tests failed out of 4
判定:4/4 通过(letterbox 预处理 / 输出编码 / fp16 精度 / CPU 预处理路径)。✔
T4|单帧图像推理 ✅ PASS
步骤
bash
cd /home/hybors/atlas300v/AscendDemo
source /usr/local/Ascend/ascend-toolkit/set_env.sh
./build/ascend_demo --model ../test_assets/test_model.om \
--image ../test_assets/test.jpg --output ../test_assets/result_img.jpg --bench 1
实测输出
[ascend] creating context for device 0...
[ascend] context created successfully
[ascend] stream created successfully
[ascend] model loaded successfully
[test] Single image mode: ../test_assets/test.jpg
[infer] DVPP path declined; CPU fallback
[ascend] Execute: copying input to device...
[ascend] Execute: running model...
[ascend] Execute: synchronizing stream...
[ascend] Execute: inference completed in 0.25 ms
[test] Detection completed in 132.94 ms
[test] Preprocess: 98.52 ms
[test] Inference: 0.25 ms
[test] Detections: 3
[test] - person: 91.11% at (0,88)-(73,265)
[test] - helmet: 81.10% at (161,132)-(250,309)
[test] - no_helmet: 76.12% at (338,176)-(426,353)
[test] Visualization saved to ../test_assets/result_img.jpg
判定:模型加载成功、推理下发成功、输出与合成模型的设计值(0.90 / 0.80 / 0.75,fp16 舍入后为 0.9111 / 0.8110 / 0.7612)逐项吻合,检测框坐标与模型内固定框一致,可视化图正常输出。✔
T5|视频流水线推理 ✅ PASS
步骤
bash
./build/ascend_demo --model ../test_assets/test_model.om \
--video ../test_assets/test_video.mp4 --output ../test_assets/result_video.mp4 \
--bench 75 --no-track
实测输出
opened video: 640x480, 25.00 FPS, 75 frames
preprocess: CPU | tracking: OFF | frames: 75 | avg preprocess 47.32 ms | avg inference 0.14 ms | 7173.42 FPS (inference only)
判定:75 帧全流程(解码 → 预处理 → 推理 → 后处理 → 编码输出)跑通,无丢帧、无报错,可视化视频正常生成。✔
T6|Python 扩展模块 ✅ PASS
步骤
bash
cd /home/hybors/atlas300v/AscendDemo
source /usr/local/Ascend/ascend-toolkit/set_env.sh
.venv/bin/python -c "import sys; sys.path.insert(0,'build'); import AscendInfer; print(AscendInfer.__file__)"
实测输出
/home/hybors/atlas300v/AscendDemo/build/AscendInfer.cpython-38-x86_64-linux-gnu.so
判定:pybind11 生成的 Python 扩展与 CANN 运行时正确链接并可导入。✔
注意:扩展需要
LD_LIBRARY_PATH包含 CANN 的lib64(否则报ImportError: libmsprofiler.so: cannot open shared object file),且.so位于build/下,需自行加入sys.path。
T7|PCIe 链路稳定性 ✅ PASS
步骤(宿主)
bash
dmesg | grep -i -E "CmpltAbrt|AER:"
实测结果
[ 554.553021] vfio-pci 0000:18:00.0: [15] CmpltAbrt (First)
[ 554.553071] pcieport 0000:17:00.0: AER: device recovery successful
判定 :整轮测试(含 T4/T5/T8 的多次推理与重负载)结束后,宿主 AER 累计仍为 1 次 ,且该次发生在固件补装之前 (宿主开机后第 554 秒的旧崩溃)。固件修复后零新增,链路稳定。✔
T8|AICore 算力加载验证 ✅ PASS
这一项回答"算术到底是不是 NPU 干的"。方法与结论见 §5.5,摘要如下。
探针模型 :构造一个依赖输入、无法被常量折叠 的重模型------把 image[1,3,544,960] 展平后 reshape 成 [1248,1248](批量维 1248),接 16 级 MatMul,合计 33.9 GMAC = 67.8 GFLOP/次 ;.om 中 17 个权重矩阵全部保留(om_info_list 权重字节 54,358,016),证明链式矩阵乘没有被化简掉。
证据一:墙钟斜率 (bench N 两点求每帧耗时)
| 模型 | bench 3 | bench 13 | 每帧 |
|---|---|---|---|
| 合成小模型(算力可忽略) | 3.98 s | 4.92 s | 94 ms |
| 重模型(67.8 GFLOP/帧) | 5.12 s | 5.92 s | 80 ms |
重模型每帧没有付出额外墙钟代价 。若这 67.8 GFLOP 跑在 Host CPU(实测约 13 GFLOPS),每帧需要约 5 秒。
证据二:AICore 利用率计数器 (npu-smi info -t usages -i 256 -c 0 高频采样)
Aicore Usage Rate(%) : 3 ← 密集模型执行期间(连续 6 次采样均为 3)
Aicore Usage Rate(%) : 0 ← 运行结束、空闲后
证据三:未加载模拟器库 ------正常运行环境下 LD_PRELOAD 与 SIMULATOR_HOME 均为空,即未加载 libruntime_camodel.so / libcamodel.so,走的是 CANN 真实运行时。
判定 :算术由 NPU 的 AICore 执行,未退化为 Host CPU 执行。✔
数值保留 :按 67.8 GFLOP 折算的等效算力高于 310P 标称 FP16 峰值,怀疑 atc tiling 对链式 MatMul 做了部分化简(
om_info_list只能证明权重未被整体折成一个常量)。因此本报告不给出等效 TFLOPS 数字,绝对算力基线需用真模型另测(见 §7)。
5. 关键问题与解决方案
本节是本报告最重要的部分------不照做就会踩坑。
5.1 驱动 DKMS 编译失败:-Werror=type-limits
现象
driver rebuild failed.
driver map or rebuild failed.
根因是 Linux 5.15 的 GENMASK_INPUT_CHECK 宏原版长这样:
c
#define GENMASK_INPUT_CHECK(h, l) \
(BUILD_BUG_ON_ZERO(__builtin_choose_expr( \
__is_constexpr((l) > (h)), (l) > (h), 0)))
__builtin_choose_expr 的两个分支中同时出现有符号/无符号比较,驱动工程以 -Werror 编译时直接告警转错误(-Werror=type-limits)。
换内核无效 :5.15.0-46 与 5.15.0-139 的 bits.h / find.h 逐字节相同;驱动包内只预编译了 openEuler 4.18 / 5.10 的内核。
解法(改内核头文件,不改驱动源码)
bash
F=/usr/src/linux-headers-5.15.0-139-generic/include/linux/bits.h
sudo cp "$F" "$F.orig-ascend"
# 把 (l) > (h) 改为 (long)(l) > (long)(h)
为什么不改驱动源码:安装器每次运行都会重新解压驱动包,源码补丁会被覆盖;改内核头则一次生效、两个内核都受益,且断言语义保持不变。
结果 :编译零错误,32 个 .ko 落到 /lib/modules/5.15.0-139-generic/updates/,npu-smi 25.5.2 装于 /usr/local/sbin/。
5.2 ★ 固件漏装 → 第一次推理必崩虚拟机
现象
- Guest:CANN plog 停在
[npu_driver.cc:6929] GetDeviceStatus: GetDeviceStatus status=1.,runtime 无限轮询等设备 ready - 宿主:
vfio-pci 0000:18:00.0: [15] CmpltAbrt (First)、aer_agent=Completer ID(卡自己 中止事务)、TLP Header 60000010 000000ff 0000387f fe000000→AER: device recovery successful→ QEMU 退出 → PVEstatus: internal-error - 宿主冷重启后仍以完全相同的 TLP 头复现(确定性失败,不是卡被 wedged)
根因 :驱动包 .run --full 不包含固件。安装日志里的铁证:
[Firmware] [INFO]UserCommand: Ascend-hdk-310p-npu-firmware_7.8.0.7.220.run --version
[Driver] [WARNING]old firmware not installed, stop version relationship check
固件安装器只被调用过一次,且是 --version 查询模式 。卡上当时只有 3 个固件组件(hboot1a/b、hlink,出厂旧版 1.82.22.2.220),而配套包定义了 6 个(另含 lpddr_mcu.bin 等 LPDDR 控制器固件)。
解法 :见 §3.4,单独执行固件包 + 重启虚拟机。修复后固件版本变为 7.8.0.7.220,崩溃消失。
5.3 ★ "固件不支持在虚拟机安装"------这个限制在直通下不触发
华为文档明写"固件包不支持在虚拟机安装和卸载",很容易据此认为"必须在物理机刷固件 → 宿主要装 Ascend 驱动 → 宿主内核 7.0.6 编译驱动风险极高 → 整条路走不通"。
这个结论是错的。 该限制的实现是固件安装器 install.sh 中的 vmCheck():
bash
"${Install_Path_Param}"/driver/tools/upgrade-tool --device_index ${global_top_up_chip} --phymachflag >& /dev/null && ret=$? || ret=$?
if [ ${ret} -eq 2 ]; then
log "[ERROR]not a physical-machine, firmware upgrade does not support."
return 1
fi
退出码 2 = 非物理机 → 拒绝。VM 内实测:
$ sudo /usr/local/Ascend/driver/tools/upgrade-tool --device_index 0 --phymachflag
{"device_id":0 phy mach}
rc=0 # ← 返回 0,不是 2
驱动把 vfio 直通卡识别为物理机(它看到的确实是一张真实 PCIe 卡),闸门放行。其余三个前置检查同样可过:
| 检查 | 判据 | 实测 |
|---|---|---|
firmwareHostReady |
扫 /sys/bus/pci/devices/,vendor ∈ `0x19e5 |
0xffff |
toolsExistCheck |
upgrade-tool 存在 |
✔ |
firmwareDeviceReady 8 |
upgrade-tool --system_version 能枚举到芯片 |
返回 {"device_id":0, "version":25.5.2} ✔ |
附带发现:驱动安装日志里有
FEATURE_VIRT_SCENE is : y------ 驱动包本身知道虚拟化场景,这也是它把卡认作物理机的原因。
5.4 apt 源缺 focal-updates → OpenCV 依赖链断掉
现象 :libopencv-dev 装不上或装到不完整版本(libgphoto2-6 需要 2.5.25,源里只有 dev 2.5.24)。
解法 :换清华镜像并显式补上 focal-updates / focal-security(见 §3.2)。换完 dpkg --audit 干净。
5.5 ★ aclrtGetRunMode()==ACL_HOST 会误判成"跑在 CPU 模拟器"
现象 :程序打印 [ascend] running in simulator/CPU mode。
CANN 8.5.2 的枚举是 ACL_DEVICE = 0 / ACL_HOST = 1,而独立探针证明所有阶段都是 ACL_HOST:
编译期枚举: ACL_DEVICE=0 ACL_HOST=1
[aclInit 后 ] err=0 runMode=1 ACL_HOST
[aclrtSetDevice 后 ] err=0 runMode=1 ACL_HOST
[aclrtCreateContext 后 ] err=0 runMode=1 ACL_HOST
[aclrtCreateStream 后 ] err=0 runMode=1 ACL_HOST
但 T8 的三路证据表明算术确由 AICore 执行。结论:310P 上该 API 恒返回 ACL_HOST,与是否真的在模拟器里跑无关。
附带澄清 :正常运行时
LD_PRELOAD与SIMULATOR_HOME均为空 → 没有 加载libruntime_camodel.so/libcamodel.so,用的就是 CANN 真实运行时。项目里AscendDemo/SIMULATOR_SUMMARY.md描述的那套LD_PRELOAD启动方式与本场景无关。
正确判定方法(三路交叉,缺一不可):
- 造一个依赖输入、不可常量折叠 的重模型(把输入 reshape 成
[K,K]再做 K 级批量矩阵乘,批量维必须 > 1,否则 MAC 数会少两个数量级) - 墙钟斜率 对比:小模型 vs 重模型,取
bench N/bench M两点求每帧耗时。跑 Host CPU 会慢几百倍 npu-smi info -t usages的Aicore Usage Rate交叉验证------该计数器分辨率很粗,小模型(每帧 0.15 ms)恒读 0,重模型才显形
5.6 其他已解决的小坑
| 现象 | 根因 | 解法 |
|---|---|---|
HwHiAiUser not exists! Please add HwHiAiUser |
驱动安装器硬性要求该用户/组 | groupadd -f HwHiAiUser + useradd -g HwHiAiUser -d /home/HwHiAiUser -m -s /bin/bash HwHiAiUser |
npu-smi 报权限错 |
/dev/davinci* 属 HwHiAiUser 组 |
sudo usermod -aG HwHiAiUser <user>,或 sg HwHiAiUser -c "npu-smi info" |
| nnal 安装失败 | 依赖 ASCEND_TOOLKIT_HOME 等环境变量 |
装完 toolkit 后 source set_env.sh,再带全套 env 重装 nnal |
atc 报 No module named 'decorator' |
当前 shell 激活了 uv venv,atc 用的是 venv 的 python | 转换前 deactivate 或另开一个干净会话(用系统 python3) |
atc 报 Value for --framework is invalid |
用了 --framework=10 |
改成 --framework=5(CANN 8.5.2 只接受 0/1/3/5) |
ctest: Unknown option --test-dir |
该选项需 CMake ≥ 3.20,本机 3.16 | cd build && ctest |
ImportError: libmsprofiler.so |
Python 扩展加载时找不到 CANN 运行时库 | source /usr/local/Ascend/ascend-toolkit/set_env.sh 后再运行 |
6. 复现步骤速查
给需要复现本报告的同事,按顺序执行即可:
bash
# ── 0. 准备:宿主 ────────────────────────────────────────────
# 把卡绑定到 vfio-pci,reboot,确认 lspci -k 显示 vfio-pci
# ── 1. 准备:客户端 OS ──────────────────────────────────────
sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak-ascend
# 换清华源 + 补 focal-updates / focal-security(见 §3.2)
sudo apt update && sudo apt install -y build-essential cmake git pkg-config \
libopencv-dev nlohmann-json3-dev libgtest-dev python3-dev python3-pip \
ffmpeg libavcodec-dev
sudo groupadd -f HwHiAiUser
sudo useradd -g HwHiAiUser -d /home/HwHiAiUser -m -s /bin/bash HwHiAiUser
echo 'vm.nr_hugepages = 2048' | sudo tee /etc/sysctl.d/99-ascend-hugepages.conf
sudo sysctl --system
# ── 2. 驱动(先打内核头补丁,见 §5.1)────────────────────────
sudo ./Ascend-hdk-310p-npu-driver_25.5.2_linux-x86-64.run --full
sudo reboot
# ── 3. 固件(★ 最容易漏,见 §5.2 / §5.3)─────────────────────
sudo ./Ascend-hdk-310p-npu-firmware_7.8.0.7.220.run --full --quiet
# 然后在 PVE 宿主:qm shutdown 101 && qm start 101
sudo /usr/local/Ascend/driver/tools/upgrade-tool --device_index -1 --component -1 --version
# 期望看到 7.8.0.7.220
# ── 4. CANN ─────────────────────────────────────────────────
yes | sudo ./Ascend-cann-toolkit_8.5.2_linux-x86-64.run --install
yes | sudo ./Ascend-cann-310p-ops_8.5.2_linux-x86-64.run --install
source /usr/local/Ascend/ascend-toolkit/set_env.sh
yes | sudo env "ASCEND_TOOLKIT_HOME=$ASCEND_TOOLKIT_HOME" \
"ASCEND_NNAE_HOME=$ASCEND_NNAE_HOME" \
"ASCEND_HOME_PATH=$ASCEND_HOME_PATH" \
"ASCEND_OPP_PATH=$ASCEND_OPP_PATH" \
"ASCEND_AICPU_PATH=$ASCEND_AICPU_PATH" \
"TOOLCHAIN_HOME=$TOOLCHAIN_HOME" \
./Ascend-cann-nnal_8.5.2_linux-x86-64.run --install
# ── 5. Python ───────────────────────────────────────────────
# venv: numpy/onnx/onnxruntime/opencv-headless/torch
# 系统 python3: numpy<1.25 protobuf<3.21 attrs psutil pyyaml cffi pillow sympy scipy requests absl-py decorator
# ── 6. 编译 + 单测 ──────────────────────────────────────────
cmake -S . -B build -DASCEND_ENABLED=ON \
-DASCEND_DIR=/usr/local/Ascend/ascend-toolkit/latest \
-DPython3_EXECUTABLE=$PWD/.venv/bin/python
cmake --build build -j$(nproc)
cd build && ctest --output-on-failure # 期望 4/4
# ── 7. 推理验收 ─────────────────────────────────────────────
source /usr/local/Ascend/ascend-toolkit/set_env.sh
./build/ascend_demo --model ../test_assets/test_model.om \
--image ../test_assets/test.jpg --output ../test_assets/result_img.jpg --bench 1
./build/ascend_demo --model ../test_assets/test_model.om \
--video ../test_assets/test_video.mp4 --output ../test_assets/result_video.mp4 --bench 75 --no-track
# ── 8. 稳定性复核(宿主)─────────────────────────────────────
dmesg | grep -c -i CmpltAbrt # 期望:固件修复后不再增长
判定标准(三条同时满足即认为本卡在该环境可用)
npu-smi info识别为310P3且 Health = OKupgrade-tool --component -1 --version报出与驱动配套的固件版本ctest4/4 通过,且推理程序能加载模型并产出正确结果
7. 结论与已知限制
7.1 结论
华为 Atlas 300V 视频解析卡在"PVE 宿主 + 整机 PCIe 直传到 Ubuntu 20.04 虚拟机"这一环境下可以正常使用。
支撑依据:
- 设备被正确枚举为 Ascend 310P3,健康状态 OK,显存与温度可读
- 驱动 25.5.2 / 固件 7.8.0.7.220 / CANN 8.5.2 三层版本严格配套
- 单元测试 4/4 通过,单帧与视频推理均产出数值正确的结果
- 重负载下 AICore 利用率实时抬升,算术确由 NPU 执行,未退化为 Host 侧
- 宿主 PCIe 错误计数在固件修复后归零,链路稳定
- 全部 8 项测试用例判定 PASS
同时确认:整条路径中最致命的一环是"固件必须单独安装,且可以在虚拟机内安装"------这两点任何一点搞错,现象都是"第一次推理直接把虚拟机打崩",且错误信息完全指不到真因。
7.2 已知限制与未覆盖项
| # | 限制 | 影响 | 后续 |
|---|---|---|---|
| 1 | DVPP 预处理未启用 ,demo 走 CPU 回退([infer] DVPP path declined; CPU fallback) |
预处理耗时占比高(单帧 98 ms 中 98 ms 是预处理),端到端实时性未达最优 | 待真模型后做 DVPP vs CPU 对照 |
| 2 | 缺真模型,性能数据仅来自合成模型 | 无法给出有业务意义的绝对算力基线 | shv54.pt 是 pickled nn.Module(依赖 models.yolo.DetectionModel),需补源码或给 TorchScript 版本 |
| 3 | npu-smi info -t board 的 Firmware Version 恒为 NA |
仅影响读数,固件实际已正确刷入 | 以 upgrade-tool 为准 |
| 4 | PCIe 链路只到 Gen3 (8 GT/s) | 带宽从理论 16 GB/s 降到约 7.9 GB/s | 宿主上游 root port 17:00.0(Sky Lake-E)硬件上限,未改 |
| 5 | 重模型折算的等效算力高于 310P 标称 FP16 峰值 | 怀疑 atc tiling 对链式 MatMul 做了部分化简 | 用真模型重新标定 |
| 6 | 未做宿主 IOMMU 模式 / 大页调优 | 当前 iommu=pt + 客户端 2GB 大页已满足需求 |
若性能不达标,再按官方 Debian 示例评估切翻译模式 + 宿主预留大页(注意宿主仅 62GB 内存,不可照抄官方的 512M×128) |
| 7 | 未测试多卡 / 多 VM 共享 / vNPU 切分 | --- | 属另一条技术路线 |
附录 A:日志与诊断位置
| 内容 | 路径 |
|---|---|
| 驱动安装日志 | /var/log/ascend_seclog/ascend_install.log |
| 固件安装日志 | /var/log/ascend_seclog/ascend_install.log([Firmware] 段)、/var/log/ascend_seclog/operation.log |
| 设备启动日志 | /var/log/device_boot_init.log |
| 驱动运行日志 | /var/log/ascend_seclog/ascend_rebuild.log |
| CANN plog(运行期) | ~/ascend/log/run/plog/plog-<pid>_*.log |
| CANN plog(debug) | ~/ascend/log/debug/plog/plog-<pid>_*.log |
| 固件升级日志 | /var/log/upgradetool/upgrade_crl.log |
| 宿主 PCIe 错误 | 宿主 `dmesg |
开启 CANN debug 日志:
bash
export ASCEND_GLOBAL_LOG_LEVEL=debug
export ASCEND_MODULE_LOG_LEVEL=GE:debug,RUNTIME:debug,ACL:debug
附录 B:常用诊断命令
bash
# 设备
sg HwHiAiUser -c "npu-smi info"
sg HwHiAiUser -c "npu-smi info -t board -i 256 -c 0"
sg HwHiAiUser -c "npu-smi info -t usages -i 256 -c 0" # AICore / DDR / DVPP 利用率
sg HwHiAiUser -c "npu-smi info -t product -i 256 -c 0" # Product Type : Atlas 300V
sg HwHiAiUser -c "npu-smi info -t pcie-err -i 256 -c 0" # PCIe 错误计数
sg HwHiAiUser -c "npu-smi info -t flash -i 256 -c 0" # SPI Flash 信息
# 固件 / 版本
sudo /usr/local/Ascend/driver/tools/upgrade-tool --device_index -1 --component -1 --version
sudo /usr/local/Ascend/driver/tools/upgrade-tool --device_index 0 --phymachflag
cat /usr/local/Ascend/driver/version.info
cat /usr/local/Ascend/firmware/version.info
# 模型
atc --mode=1 --om=xxx.om --json=/tmp/om_dump.json # dump .om 算子图与权重字节数