教程:VENTUNO Q/NPU 指南
概述
Arduino® VENTUNO™ Q 基于 Qualcomm® Dragonwing™ IQ8(QCS8275),该处理器将通用 CPU 与专用 神经网络处理单元(NPU) 配对,用于运行 AI 模型。本指南解释 NPU 究竟是什么、它与同一芯片上的 CPU 和 GPU 有何不同,以及将模型(无论是预训练、TensorFlow™ 还是 PyTorch)跑在其上的三条实用路径。
在本指南中我们将涵盖:
- NPU 是什么,以及它与 CPU、GPU 有何不同。
- QCS8275 上 Hexagon™ Tensor Processor 的规格。
- 在 NPU 上运行模型的三条受支持路径(Qualcomm® AI Hub、TensorFlow™/LiteRT、PyTorch/ONNX Runtime)。
- 在 VENTUNO Q 上设置 NPU 工具链。
- 每个 NPU 工作负载都会遇到的约束,以及如何规避。
- 对比 NPU 与 CPU 推理的基准数据。
这是一份概念与参考指南。若需动手、逐步演练,请参阅文末的 相关教程。
什么是 NPU?
NPU(Neural Processing Unit,神经网络处理单元)是专门用于执行神经网络算术的处理器核心:大量乘累加(MAC)运算,以矩阵与张量乘法的形式组织。与 CPU 一次一条分支地执行通用指令流不同,NPU 被布线为数千个小型乘累加单元组成的阵列,它们同时对不同数据块执行同一种运算。
- CPU(Central Processing Unit,中央处理器)为灵活性而建。它执行任意指令、处理分支逻辑,并支持任何数值格式(32 位浮点、64 位双精度、任意精度整数)。当工作负载是大规模简单重复的数学运算(如神经网络的矩阵乘法)时,这种灵活性会牺牲功耗与吞吐量。
- GPU(Graphics Processing Unit,图形处理器)介于两者之间:数千个更简单的核心对数据执行相同指令(SIMD),最初为像素/顶点数学设计,但通过 OpenCL 等 API 也非常适合通用矩阵计算(GPGPU)。QCS8275 上的 Adreno™ 623 GPU 即以这种方式用于图形和部分计算工作负载。
- NPU 比 GPU 更进一步:放弃对张量数学以外任何内容的支持,并将自身限制在 低精度算术——8 位或 16 位整数,或 16 位浮点——而不是 CPU 使用的 32 位浮点。作为交换,它为这一工作负载提供远高于 CPU 或 GPU 的每瓦吞吐量。
对你作为开发者的实际影响:NPU 不能像 CPU 那样运行“一个程序”。它以降低的精度运行固定的计算图(神经网络)。NPU 不能执行 FP32,因此每个图要么事先量化为 8 位或 16 位整数,要么在加载模型时由运行时转换为 16 位浮点(FP16)。量化需要更多准备,但能提供最高吞吐量;FP16 则完全不需要准备。
QCS8275 上的 CPU vs. GPU vs. NPU
| 处理器 | QCS8275 上的组件 | 执行内容 | 数据类型 | 最适合 |
|---|---|---|---|---|
| CPU | Kryo™ Gen 6(八核 Arm® Cortex®) | 任意指令、分支逻辑 | FP32/64、任意整数宽度 | 通用代码、编排、前/后处理 |
| GPU | Adreno™ 623 | SIMD 图形与通用计算(OpenCL) | FP16/FP32(部分计算路径也支持 INT8) | 3D 图形、视频处理、部分并行计算 |
| NPU | Hexagon™ Tensor Processor | 仅固定神经网络图 | INT8 / INT16(量化)、FP16(无 FP32) | 高吞吐、低功耗的神经网络推理(视觉、音频、LLM) |
QCS8275 上的 Hexagon Tensor Processor
VENTUNO Q 的 Qualcomm® Dragonwing™ QCS8275 上的 NPU 称为 Hexagon™ Tensor Processor。它在一个单元下集成三个不同的计算块:
- 一个 Hexagon™ DSP(Digital Signal Processor,数字信号处理器)核心,处理 NPU 流水线内的标量与控制流工作。
- 四路 Hexagon Vector eXtensions(HVX)——四个向量协处理器,用于宽 SIMD 数学(大量用于调整大小与颜色转换等图像前/后处理步骤)。
- 双路 Hexagon Matrix eXtensions(HMX)——一个整数和一个浮点矩阵协处理器,专为构成卷积与全连接层的稠密矩阵乘法而建。
| 规格 | 值 |
|---|---|
| 峰值 AI 性能 | VENTUNO Q 所用 QCS8275-AA 变体上最高 40 dense TOPS(每秒万亿次运算) |
| 峰值 AI 性能(QCS8275-AC 变体,未用于 VENTUNO Q) | 最高 20 dense TOPS |
| NPU 片上内存 | 每个 Hexagon Tensor Processor:1 MB L2 缓存 + 8 MB Vector-TCM(vTCM) |
| 支持的精度 | INT8(w8a8)、INT16 激活(w8a16)、FP16。FP32 不在 NPU 上执行
|
| 支持的框架 | TensorFlow™ Lite(LiteRT)、ONNX Runtime、PyTorch(通过转换) |
作为对比,VENTUNO Q 上 QCS8275 的其他计算块运行于:
| 组件 | 细节 |
|---|---|
| CPU(Kryo™ Gen 6) | 2× Prime 核心最高 2.35 GHz,2× Gold 核心最高 2.1 GHz,4× Silver 核心最高 1.95 GHz |
| GPU(Adreno™ 623) | 最高 877 MHz |
说明:
TOPS 是 8 位整数乘累加吞吐量的峰值理论值。实际推理速度还取决于模型架构、内存带宽,以及图中有多少部分能真正在 NPU 上运行(参见下方 常见约束)。
在 NPU 上运行模型的三种方式
VENTUNO Q 的 NPU 上每个 AI 工作负载都遵循相同的底层要求——降低精度、固定形状的计算图——但根据模型来源,有三条实用起点。
1. 从预优化模型开始(Qualcomm AI Hub)
最快的路径。Qualcomm® AI Hub 托管大量已训练、已量化、并已验证可在 Dragonwing™ 硬件(更具体地说是 QCS8275)上运行的模型。请注意,并非所有模型都与此芯片组兼容。
- 浏览 AI Hub 模型列表,按芯片组(
Qualcomm QCS8275 (Proxy))与精度(Quantized)筛选。 - 以 TFLite 格式(用 LiteRT 运行)或 ONNX 格式(用 ONNX Runtime 运行)下载模型。
qai-hub-modelsPython 包(pip install qai-hub-models)还为许多模型提供带正确前/后处理的现成参考实现,以及可在开发板上直接下载模型文件的fetch命令:
qai-hub-models fetch <model-id> --runtime onnx --precision w8a16 --output-dir models/
预编译的 TFLite 与 ONNX 资源与设备无关,因此 fetch 不需要芯片组或设备参数。添加 --url-only 可仅打印下载 URL 而不获取文件。
使用 Qualcomm® AI Hub 的教程见以下文档:
2. 转换 TensorFlow™ / Keras 模型(LiteRT)
TensorFlow™ 本身只在 CPU 上运行——它使用 32 位浮点数学训练与评估模型,而 NPU 无法直接执行。要到达 NPU,必须将 TensorFlow™/Keras 模型转换为 .tflite 文件——为获得最佳吞吐量量化为 INT8,或保持浮点并由运行时转换为 FP16——然后用 LiteRT(TensorFlow™ Lite 运行时的当前名称——技术与文件格式未变,仅名称重新品牌化)执行。
为此,可按以下说明操作:
- 训练或加载 TensorFlow™/Keras 模型(FP32)。
- 使用 TensorFlow™ Lite Converter 将其转换为
.tflite,应用 训练后量化(或量化感知训练以获得更好精度),使权重与激活变为 INT8。 - 用
ai-edge-litert运行生成的.tflite文件,并指向 QNN HTP delegate(libQnnTFLiteDelegate.so),使图在 NPU 而非 CPU 上执行。
运行模型时,同时准备 CPU 与 NPU 版本以便对比是个好主意。教程部分列出的示例有一个启用 NPU 的标志(例如 python3 script.py --use-npu),而留空则在 CPU 上运行。这也是确认模型是在 NPU 还是 CPU 上运行的好方法。NPU 上的性能应明显更好。
3. 转换 PyTorch 模型(ONNX Runtime)
PyTorch 模型同样不能直接在 NPU 上运行,原因相同:PyTorch 计算默认是 FP32,而 NPU 不执行 FP32。此处路径通过 ONNX 而非 TFLite:
- 使用
torch.onnx.export()将训练好的 PyTorch 模型导出为 ONNX(FP32),并使用 静态(固定)输入形状——NPU 无法针对动态形状。 - 将 ONNX 模型从 FP32 量化为 INT8。这意味着编写一个
CalibrationDataReader,向模型馈送少量代表性输入样本,然后调用 ONNX Runtime 的quantize_static(),在 QDQ(quantize-dequantize)格式中使用QUInt8激活与QInt8权重。 - 用 ONNX Runtime 运行量化模型,选择带
"backend_type": "htp"的QNNExecutionProvider以针对 NPU(或用CPUExecutionProvider与 CPU 对比)。
Qualcomm 针对此工作流的参考示例(SqueezeNet-1.1 分类器)显示 CPU 与 NPU 上每张图像延迟相当(约 7.5 ms)——这是一个有用的提醒:非常小的模型并不总是从 NPU 受益,因为固定开销(数据编组、会话设置)在该规模下可能占主导。随着模型大小与计算密度增加,收益会增长,如上所述的 LiteRT 与 TFLite/TensorFlow™ 示例所示。
这是本合集中 ONNX Runtime 教程使用的路径,它使用预量化的 AI Hub 模型而非自定义量化模型,但通过相同的 QNNExecutionProvider 机制针对 NPU。
第四种选项:使用 Edge Impulse 的无代码训练
若要构建并训练 自定义 模型而无需手写量化流水线,VENTUNO Q 还与 Edge Impulse Studio 集成,后者在一个工作流中处理数据收集、训练,以及导出 NPU 就绪的量化模型。这超出了本指南范围,但如果你的目标是自定义分类器而非现有已发布模型,则值得了解。
在 VENTUNO Q 上设置 NPU 工具链
无论你采用上述三条路径中的哪一条,到达“在 NPU 上运行”这一点始终涉及相同的开发板侧设置:访问 shell、创建隔离的 Python 环境,并安装与模型格式匹配的运行时。
访问开发板 Shell
所有命令都在 VENTUNO Q 上 运行,使用以下方式之一:
- SSH:
ssh arduino@<device-ip> - ADB:
adb shell - 直接: 将键盘、鼠标和显示器连接到开发板(它运行完整的 Ubuntu Linux 桌面,也支持 Debian)。
安装 Qualcomm AI Runtime
NPU 由 Qualcomm® AI Runtime(QAIRT) 驱动,它提供 LiteRT 与 ONNX Runtime 在推理时加载的 QNN HTP 后端。它 默认未 安装在 VENTUNO Q 镜像上,也不会被下面任何 pip 包拉取——没有它,每次 NPU 调用都会因库加载错误而失败。
从开发板的 apt 仓库安装:
sudo apt update
sudo apt install qairt-libs qairt-dsp-binaries
这会将 QNN 后端库安装到 /usr/lib/,包括本合集示例引用的两个:
/usr/lib/libQnnHtp.so— HTP(Hexagon Tensor Processor)后端,由 ONNX Runtime 使用。/usr/lib/libQnnTFLiteDelegate.so— LiteRT delegate,由 TFLite 示例使用。
继续之前请验证安装:
ls /usr/lib/libQnnHtp.so /usr/lib/libQnnTFLiteDelegate.so
说明:
因为
/usr/lib在默认库搜索路径上,delegate 可按名称(libQnnTFLiteDelegate.so)加载,而无需指定完整路径。
创建 Python 虚拟环境
Ubuntu 24.04 不允许向系统 Python 执行 pip install,因此请先创建虚拟环境:
python3 -m venv .venv
source .venv/bin/activate
每个新会话开始时重新运行 source 命令。
选择运行时:LiteRT vs. ONNX Runtime
两个运行时最终都将量化图交给相同的底层 QNN HTP 后端(Qualcomm 的 Hexagon Tensor Processor 驱动)——选择主要取决于你的模型格式。
LiteRT(.tflite 模型)
|
ONNX Runtime(.onnx 模型)
| |
|---|---|---|
| 安装 | pip install ai-edge-litert==1.3.0 opencv-python numpy
|
pip install qai-hub-models,然后换成特殊的 QNN wheel(见下文)
|
| NPU delegate/provider | libQnnTFLiteDelegate.so,后端 "htp"
|
QNNExecutionProvider,"backend_type": "htp"
|
| 典型源模型 | TensorFlow™/Keras、AI Hub TFLite 导出 | PyTorch、AI Hub ONNX 导出 |
LiteRT 设置:
pip install ai-edge-litert==1.3.0 opencv-python numpy
from ai_edge_litert.interpreter import Interpreter, load_delegate
qnn_delegate = load_delegate("libQnnTFLiteDelegate.so", options={"backend_type": "htp"})
interpreter = Interpreter(model_path="model.tflite", experimental_delegates=[qnn_delegate])
ONNX Runtime 设置(启用 QNN 的构建不是普通的 pip install onnxruntime——完整三步安装见 ONNX Runtime 教程):
pip install qai-hub-models
pip uninstall -y onnxruntime
pip install onnx==1.18.0
wget https://cdn.edgeimpulse.com/qc-ai-docs/wheels/onnxruntime_qnn-1.23.0-cp312-cp312-linux_aarch64.whl
pip install onnxruntime_qnn-*-linux_aarch64.whl
import onnxruntime as ort
providers = [("QNNExecutionProvider", {"backend_type": "htp", "library_path": "/usr/lib/libQnnHtp.so"})]
sess = ort.InferenceSession("model.onnx", providers=providers)
针对 NPU 时的常见约束
这些限制适用于所有三条路径,也解释了本合集教程为何如此组织:
- FP32 永远不会在 NPU 上运行,但量化并非离开 FP32 的唯一方式。 NPU 执行 INT8、INT16 与 FP16 张量——而非 FP32。因此未量化模型并不自动成为 CPU 模型:QNN HTP 后端在加载时将 FP32 图转换为 FP16,并在 NPU 的浮点矩阵协处理器上运行。量化为 INT8 可获得最高吞吐量与最小模型,但直接来自 AI Hub 的 FP32 模型仍会到达 NPU,精度大致为 FP16。后端真正无法映射的算子会卸载到 CPU,而不是直接失败——如果你假定整张图都在 NPU 上运行,这可能静默隐藏性能问题。LiteRT 与 ONNX Runtime 都允许禁用此自动 CPU 回退(例如 ONNX Runtime 中的
session.disable_cpu_ep_fallback),使不受支持的算子报错而不是安静回退。 - 仅固定输入形状。 使用动态维度导出的模型(常见默认值)必须在 NPU 能够针对它们之前转换为静态形状——参见 ONNX Runtime 教程 中的
make_dynamic_shape_fixed步骤。 - 并非每个子图都同等受益。 在混合流水线中(例如检测器向关键点模型馈送),某一阶段的 NPU 量化权重可能对给定输入分布校准不佳,而其 CPU/浮点对应物则不然——Face Mesh 教程 正好记录了这种情况:人脸检测器故意使用浮点权重在 CPU 上运行,而只有关键点模型在 NPU 上运行。
- 小模型可能看不出加速。 如上所述 SqueezeNet PyTorch 示例所示,固定的每次推理开销可能超过 NPU 在非常小的图上的原始吞吐量优势。
基准:NPU 快多少?
以下数据在运行 Ubuntu 24.04 的 VENTUNO Q 上测得,在一次预热后对重复推理取平均。第一个模型量化为 INT8;第二个是未量化的 FP32 导出,运行时将其转换为 FP16 以在 NPU 上运行:
| 模型 | 模型精度 | CPU | NPU(QNN HTP delegate) | 加速比 |
|---|---|---|---|---|
| 人脸关键点检测器(192×192) | INT8(w8a8)
|
9.10 ms | 0.46 ms | ~20x |
| YOLOv7(640×640) | FP32 → FP16 | 440.42 ms | 12.60 ms | ~35x |
YOLOv7 数据很好地说明了 FP16 路径:模型从 Qualcomm® AI Hub 导出时未量化,AI Hub 自己的分析器将全部 201 个操作放在 NPU 上。将其 NPU 输出与同一图在 CPU 上运行对比,中位相对偏差约为 5.2 × 10⁻⁴,这与 FP16 精度而非 FP32 一致——确认运行时将图转换为半精度以执行它。
以下额外数据来自 Qualcomm 在 Dragonwing™ 硬件上的参考示例,说明典型相对加速,而非 VENTUNO Q 特定测量——请将其视为权衡形态(延迟 vs. 精度 vs. 模型大小)的指导,而非对任何特定模型的保证。
| 模型 | CPU(FP32) | NPU(量化) | 加速比 | 说明 |
|---|---|---|---|---|
| Vision Transformer(LiteRT) | ~300 ms | ~14 ms | ~21x | 大型、计算密集模型——NPU 优势最大 |
| Cats 分类器(TensorFlow™/Keras → TFLite) | 12.9 ms(94.37% 精度) | 3.809 ms(88.51% 精度) | ~4x | 量化带来的小幅精度权衡 |
| SqueezeNet-1.1(PyTorch → ONNX) | ~7.5 ms | ~7.5 ms | ~1x | 小模型——固定开销占主导 |
一般规律:模型越大、矩阵乘法越重,NPU 的优势就越大。小或轻量模型在计入开销后可能几乎没有收益。
本合集中的教程
本指南是以下动手教程的概念入口,所有这些教程都在 VENTUNO Q 的 NPU 上运行推理:
- Getting Started with Qualcomm AI Hub on the VENTUNO Q — 完整 AI Hub 工作流:查找兼容模型、导出/编译,并在 NPU 上运行静态图像示例。
- ONNX Runtime on the VENTUNO Q — 安装启用 QNN 的 ONNX Runtime 构建、修复动态形状,并运行实时眼球注视跟踪示例。
- Real-Time Face Detection on the VENTUNO Q — 使用
face_det_lite模型通过 LiteRT 进行实时人脸检测。 - Real-Time Face Mesh on the VENTUNO Q — 混合 CPU/NPU 流水线:CPU 上做人脸检测,NPU 上做 468 点关键点网格。
- Real-Time Semantic Segmentation on the VENTUNO Q — 使用 SegFormer 模型在 NPU 上完全进行实时逐像素场景分割。
结论
VENTUNO Q 的 QCS8275 上的 Hexagon™ Tensor Processor 用 CPU 的灵活性换取最高 40 dense TOPS 的降低精度神经网络吞吐量。无论你采用三条路径中的哪一条——预优化 AI Hub 模型、转换后的 TensorFlow™/Keras 模型,或转换后的 PyTorch 模型——目的地都是相同的:通过 QNN HTP 后端运行的固定、降低精度的图,经由 LiteRT 或 ONNX Runtime 访问。从这里开始,相关教程将带你在真实模型上端到端走完每条路径。
原文:https://docs.arduino.cc/tutorials/ventuno-q/npu-guide/ 本页为 Arduino 官方教程的中文翻译,供内部查阅。命令与代码保持原文。