Skip to content

约 5 分钟阅读

15. 端侧 NPU 加速导读 ​

14. 模型与部署选型 的结尾留了一句话:NPU 不是替换一个 provider 字符串就能完成的通用优化,各家后端的支持范围、模型转换和算子限制都不同,需要单独的交付链路。这个子系列就是把那条单独的链路从头走一遍,用的是一条具体的线:把一个流式语音识别模型的编码器,放到一台鸿蒙手机的 NPU 上。

起点是一个已经能用的 CPU 方案。模型是流式 zipformer2 transducer,分成 encoder、decoder、joiner 三件,每次吃一拍——64 帧、640 ms 音频,带着 116 路缓存状态进出,加上音频本身一共 117 路输入、117 路输出。这一拍在手机上走 4 线程 INT8,耗时 69 ms,实时毫无压力。问题出在连续使用:开一小时会议,机身温度和耗电都明显。手机上有一颗 NPU,直觉非常自然——把最重的 encoder 搬上去,应该又快又省电。

这个直觉只对了一半,而错的那一半花了大部分时间才弄清楚。

先把结论放在前面 ​

问题实测答案
encoder 能不能上这颗 NPU能,但必须换一条通路,并且 FP32 原图不行
上去之后快了吗没有。每拍 147 ms,CPU 是 69 ms,慢 2.1 倍
还跟得上实时吗跟得上。640 ms 一拍连续跑 937 拍,一次超时都没有,占空比 23%
省电吗省。同样的音频量,每拍能耗 63 mJ 对 199 mJ,NPU 低约 69%
那到底该不该用看目标。要功耗和温升就用,要时延就别用

一句「NPU 更快更省电」在这里被拆成了两半:能耗这一半成立,时延那一半不成立,而且不是没调好,是结构性的。把这两半分开,是整个系列最重要的一件事——它决定了后面每一次优化该往哪个方向使劲。

两条通往 NPU 的路 ​

同一份导出的 ONNX 模型,在这台设备上有两条完全不同的上机方式,区别不在模型,而在「谁来判断这张图能不能交给 NPU」。

同一份模型,两条通往 NPU 的路

左边一条是在线通路:主机上的转换器只负责把 ONNX 换成设备运行时认识的图格式,真正的判断发生在设备加载的时候,由系统服务做一次在线能力校验。通过了才编译,不通过只回一个 Authentication failed, input model cannot run by npu——没有节点名、没有体量数字,什么线索都不给。编码器在这里被挡了很久。

右边一条是离线通路:主机上的离线编译器直接把图编译成这类芯片能加载的模型文件,设备侧只做一次兼容性确认(返回 0 表示收),然后构造执行器、绑定 117 路张量。这条路上根本不存在那次在线校验,所以也不会有那个报错。编码器最后是从这条路上去的。

两条路的失败原因互不通用,这一点在排查时格外容易踩空:在线通路量出来的体量上限解释不了离线通路的失败,反过来把在线通路的图格式喂给离线设备,会在构建阶段直接失败,而不会给出那个在线校验的错误。把两条路的证据混在一起分析,会得到一个听起来自洽、实际上两边都不成立的结论。

这几篇分别回答什么 ​

篇目回答的问题
16. 模型压缩与体量门槛同样是 169 MB 和 168 MB,为什么一个被拒一个通过;哪一级压缩在运行时会被还原
17. 图转换与算子适配设备拒收的算子怎样等价替换,重写之后凭什么说没改错
18. 时延、功耗与内存怎么测每个数字的采集条件、口径和失效前提;哪些读数是废的
19. 为什么没有变快五个听起来合理的解释怎样被实测逐个否掉,真因是什么,采用边界在哪

按顺序读是一条完整的排查线:先把模型塞进去(16),再让设备认识这张图(17),然后把数字测对(18),最后解释数字并决定用不用(19)。如果手上已经有一条跑通的链路,只是想知道结论和边界,可以直接读 19。

量化、精度格式本身的原理不在这里重讲,需要补的话看 数值精度与量化;准确率指标的定义和计算口径在 21. 质量评估与排错。

这些数字是在什么上面测的 ​

经验类内容最怕的是数字脱离条件。这个系列里所有实测数据都来自同一套环境,先写清楚,后面各篇不再重复:

项值
设备一台搭载麒麟 8020 的鸿蒙手机,HarmonyOS 6.0.2,API 22;GPU 结论在另一台 API 23 的鸿蒙手机上交叉确认
模型流式 zipformer2 transducer 的 encoder,固定形状并常量折叠后 3766 个节点,去量化 FP32 约 617 MB
一拍64 帧 = 640 ms 音频
CPU 对照ONNX Runtime 1.16.3,INT8,4 线程
离线工具链该平台的 CANN Kit DDK,tools-next 6.1.1.0,2026-10-28 取得
采集时间2026-10-28 至 2026-10-30

时延和功耗都用全零输入测,只衡量计算和搬运,不代表识别准确率。准确率要用真实音频和参考文本单独评,这是两件事,18. 时延、功耗与内存怎么测 会把这条边界讲清楚。

工具链版本和设备系统版本都写明了日期,因为它们是这里面最易变的部分:同一颗芯片换一个系统版本,支持的算子集和体量门槛都可能挪位置,结论需要重测而不是照抄。

一条贯穿整个系列的线 ​

为了让各篇能互相印证,后面四篇用的是同一条线,不换例子:

  1. 一张 617 MB 的 FP32 编码器图,在在线通路上被体量门槛挡住;
  2. 换成 FP16 能过门槛,但代价是内存涨;换成权重量化文件虽小却照样被拒;
  3. 换到离线通路,先把设备拒收的算子等价重写,再做后量化,得到 150.3 MiB 的模型,设备收下;
  4. 设备收下之后,按真实节拍测时延、功耗、内存,发现慢了但省电;
  5. 为了解释「为什么慢」,用一批合成模型在同一颗 NPU 上量出几把尺子,用尺子否掉五个假说,最后定位到张量形状;
  6. 顺着真因去填满批次,又撞上一堵新的算子墙,补救方案在记录时点还没验证完。

最后这一条是故意留着的。这个系列记录的是一次尚未结束的工程过程,哪些是实测、哪些是推算、哪些还没做,各篇都会标清楚——因为在这类工作里,把"还没验证"写成"已经成立",比慢 2 倍危险得多。

下一篇:16. 模型压缩与体量门槛,先解决最直接的问题——模型根本放不进去。

别急,先让缓存热一下。