教程:VENTUNO Q/NPU 指南

来自WindwizPi wiki
Windwiz​(留言 | 贡献)2026年9月28日 (一) 05:58的版本 (导入 VENTUNO Q 中文教程)
(差异) ←上一版本 | 最后版本 (差异) | 下一版本→ (差异)

概述

Arduino® VENTUNO™ Q 基于 Qualcomm® Dragonwing™ IQ8(QCS8275),该处理器将通用 CPU 与专用 神经网络处理单元(NPU) 配对,用于运行 AI 模型。本指南解释 NPU 究竟是什么、它与同一芯片上的 CPU 和 GPU 有何不同,以及将模型(无论是预训练、TensorFlow™ 还是 PyTorch)跑在其上的三条实用路径。

在本指南中我们将涵盖:

  1. NPU 是什么,以及它与 CPU、GPU 有何不同。
  2. QCS8275 上 Hexagon™ Tensor Processor 的规格。
  3. 在 NPU 上运行模型的三条受支持路径(Qualcomm® AI Hub、TensorFlow™/LiteRT、PyTorch/ONNX Runtime)。
  4. 在 VENTUNO Q 上设置 NPU 工具链。
  5. 每个 NPU 工作负载都会遇到的约束,以及如何规避。
  6. 对比 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-models Python 包(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 运行时的当前名称——技术与文件格式未变,仅名称重新品牌化)执行。

为此,可按以下说明操作:

  1. 训练或加载 TensorFlow™/Keras 模型(FP32)。
  2. 使用 TensorFlow™ Lite Converter 将其转换为 .tflite,应用 训练后量化(或量化感知训练以获得更好精度),使权重与激活变为 INT8。
  3. 用 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:

  1. 使用 torch.onnx.export() 将训练好的 PyTorch 模型导出为 ONNX(FP32),并使用 静态(固定)输入形状——NPU 无法针对动态形状。
  2. 将 ONNX 模型从 FP32 量化为 INT8。这意味着编写一个 CalibrationDataReader,向模型馈送少量代表性输入样本,然后调用 ONNX Runtime 的 quantize_static(),在 QDQ(quantize-dequantize)格式中使用 QUInt8 激活与 QInt8 权重。
  3. 用 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 上运行推理:

结论

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 官方教程的中文翻译,供内部查阅。命令与代码保持原文。