2、TinyML基础回顾:嵌入式设备、微控制器、神经网络推理的基本流程与资源约束

TinyML 的核心场景是在资源极度受限的嵌入式设备上运行神经网络推理。要准确 profiling 推理耗时,首先必须理解目标硬件平台的架构特征、神经网络推理在设备上的完整执行链路,以及各类资源约束如何影响性能表现。本章将系统梳理嵌入式设备与微控制器的关键差异、推理链路的基本流程,以及内存、算力、功耗等硬约束,为后续章节的耗时拆分与定位建立必要的知识基础。

嵌入式设备 微控制器 (MCU) 推理链路与资源约束 应用处理器 (AP) Linux/RTOS,MMU,高主频 典型资源 RAM 256MB~2GB,eMMC/SD 代表芯片 树莓派、Jetson Nano、RK3588 Profiling 特点 可用 perf/valgrind 等工具 MCU 核心特征 无 MMU,裸机/RTOS,Flash 运行 典型资源 RAM 16KB~1MB,Flash 256KB~4MB 代表芯片 STM32F4、ESP32、RP2040、nRF52840 Profiling 特点 依赖硬件计数器、GPIO 翻转、JTAG ① 数据采集 传感器 → 预处理 ② 模型加载 解析 TFLite/ONNX 图结构 ③ 算子执行 Conv/DepthwiseConv/FC 等 ④ 后处理 Softmax/阈值判断/输出 资源约束 • 算力:~10-100 MOPS • 内存:KB 级 SRAM • 功耗:mW 级预算 • 存储:Flash 有限 对比 映射

上图展示了嵌入式设备与微控制器在资源量级上的巨大差异,以及神经网络推理在 MCU 上的典型执行链路。理解这些差异是 profiling 工作的前提——同样的模型在应用处理器上可能只需毫秒级推理,而在 MCU 上则可能耗时数百毫秒甚至秒级。下面从硬件基础、推理流程、资源约束三个维度展开。

2.1 嵌入式设备与微控制器的核心差异

嵌入式设备是一个宽泛的概念,涵盖从简单的 8 位单片机到复杂的应用处理器。在 TinyML 语境下,我们主要关注两类目标:微控制器(MCU)和低功耗应用处理器(AP)。两者在架构、操作系统、内存管理和调试手段上存在本质区别,这些区别直接决定了 profiling 方法的选择。

对比维度 微控制器(MCU) 低功耗应用处理器(AP)
CPU 主频 16MHz ~ 240MHz(Cortex-M 系列) 1GHz ~ 2GHz(Cortex-A 系列)
内存 SRAM 16KB ~ 1MB,无外部 DRAM DDR3/DDR4,256MB ~ 4GB
存储 Flash 256KB ~ 4MB,代码就地执行(XIP) eMMC/SD 卡,代码加载到 RAM 执行
操作系统 裸机或 RTOS(FreeRTOS、Zephyr) Linux 或 Android
MMU 无,直接物理地址访问 有,支持虚拟内存和进程隔离
调试接口 JTAG/SWD,硬件断点,ITM 跟踪 JTAG,perf,gdb,ftrace
典型功耗 mW 级(1~100mW) W 级(1~10W)

在 profiling 时,MCU 上无法直接运行 Linux 的 perf 工具,也没有足够的 RAM 来存放完整的 profiling 日志。因此,MCU 上的耗时分析通常依赖硬件定时器(DWT->CYCCNT)、GPIO 翻转示波器测量或JTAG 跟踪。而应用处理器上则可以使用成熟的 perf 工具链,但需要注意缓存一致性、中断延迟等因素对推理耗时的影响。

关键认知:MCU 的 Flash 执行速度通常慢于 RAM 执行。如果模型权重存储在 Flash 中,每次读取权重都需要通过 Flash 接口,这会显著增加算子执行时间。在 profiling 时,需要区分计算时间和访存时间,两者往往各占一半甚至访存占比更高。

2.2 神经网络推理在 MCU 上的基本流程

一个完整的 TinyML 推理链路可以拆分为四个阶段:数据采集与预处理、模型加载与解析、算子执行、后处理与输出。每个阶段都有不同的耗时特征和优化空间。

阶段一:数据采集与预处理

传感器数据(如麦克风 PCM 音频、IMU 加速度计数据、摄像头图像)首先需要被采集并转换为模型输入张量。预处理包括:

  • 归一化:将原始 ADC 值或传感器原始数据映射到 [0,1] 或 [-1,1] 区间。
  • 重采样/裁剪:将数据调整到模型要求的输入尺寸。
  • 数据格式转换:例如将 int16 PCM 转换为 float32 或 int8 量化值。

预处理耗时往往被低估。例如,一个 16000Hz 的 1 秒音频帧,如果做浮点归一化,在 100MHz 的 MCU 上可能需要 5~10ms,这已经占整个推理预算的 10% 以上。

阶段二:模型加载与解析

TinyML 框架(如 TensorFlow Lite Micro、CMSIS-NN)通常将模型编译为 C 字节数组,在启动时解析图结构。解析过程包括:

  1. 遍历算子节点,建立执行顺序。
  2. 分配张量内存(静态分配或 arena 分配)。
  3. 检查算子是否被当前内核支持。

模型加载通常只执行一次,但如果使用解释器模式(非编译执行),每次推理都会重新遍历图结构,这会引入固定开销。在 profiling 时,需要将一次性加载时间和每次推理时间分开统计。

阶段三:算子执行(核心耗时)

算子执行是推理链路中耗时占比最大的部分,通常占 80%~95%。常见算子包括:

  • 卷积(Conv2D):计算量最大,通常占 50%~70% 的推理时间。
  • 深度可分离卷积(DepthwiseConv2D):MobileNet 系列的核心算子,计算量约为标准卷积的 1/9。
  • 全连接(FullyConnected):本质是矩阵乘法。
  • 激活函数:ReLU、Sigmoid、Tanh 等,在 MCU 上 Sigmoid 的 exp 计算可能成为瓶颈。
  • 池化(MaxPool/AvgPool):访存密集,计算量小。

算子执行时间受三个因素影响:算法复杂度(MAC 次数)、内存带宽(权重和激活值的读取速度)、CPU 流水线效率(分支预测、SIMD 指令使用)。在 Cortex-M4/M7 上,CMSIS-DSP 库提供的 SIMD 优化可以显著加速卷积运算。

阶段四:后处理与输出

后处理包括 Softmax 归一化、阈值判断、类别映射等。Softmax 中的 exp 运算在 MCU 上可能耗时较长,通常使用查表法或近似计算优化。输出阶段可能涉及 UART 发送、LED 控制或无线传输,这部分时间取决于外设速度。

Profiling 建议:在代码中为每个阶段插入 GPIO 翻转点,使用逻辑分析仪或示波器测量各阶段耗时。例如,在预处理开始前拉高 GPIO,预处理结束后拉低,即可精确测量预处理耗时。这种方法开销极小(仅几条指令),且不影响实时性。

2.3 资源约束对推理性能的影响

TinyML 的"Tiny"不仅指模型小,更指硬件资源的极端受限。以下四类约束直接决定 profiling 时需要关注的性能瓶颈。

算力约束(Compute Bound)

MCU 的算力通常在 10~100 MOPS(百万次操作每秒)。以 STM32F746 为例,Cortex-M7 @216MHz,支持 SIMD,理论峰值约 432 MOPS,但实际卷积运算效率通常只有 30%~50%。一个 1MB 的 MobileNetV1 模型(约 570M MACs)在这样算力下需要 2~5 秒才能完成推理,这显然不满足实时性要求。因此,TinyML 模型通常控制在 100K~5M MACs 范围内。

内存约束(Memory Bound)

MCU 的 SRAM 通常只有几十到几百 KB。模型权重、激活值、中间缓冲区都需要在 SRAM 中分配。当内存不足时,框架会采用内存复用策略(如 TFLite Micro 的 arena 机制),但这可能导致某些算子无法同时驻留权重和激活值,从而增加 Flash 读取次数。在 profiling 时,需要关注:

  • 权重是否全部驻留 SRAM,还是部分从 Flash 按需读取。
  • 激活值缓冲区是否发生溢出到 Flash(通常不会,但会导致分配失败)。
  • 内存对齐是否影响 SIMD 指令效率(未对齐访问可能导致异常或性能下降)。

功耗约束(Power Bound)

电池供电设备对功耗有严格限制。推理耗时越长,平均功耗越高。例如,一个 10mA 电流、3.3V 供电的设备,如果推理耗时从 50ms 增加到 200ms,则单次推理能耗从 1.65mJ 增加到 6.6mJ。在 profiling 时,除了关注耗时,还应结合电流探头测量实际功耗,评估能耗效率(MACs/mJ)。

存储约束(Storage Bound)

Flash 容量限制了模型大小。一个 300KB 的模型在 1MB Flash 的 MCU 上可能占用 30% 的空间,但还需要存放固件代码、RTOS 内核、传感器驱动等。模型压缩(量化、剪枝、蒸馏)是缓解存储约束的主要手段,但会引入精度损失,需要在 profiling 时权衡。

常见误区:很多开发者只关注算子计算时间,忽略了数据搬运时间。在 MCU 上,从 Flash 读取 4 字节权重可能需要 2~3 个时钟周期,而 CPU 执行一次 MAC 运算只需 1 个时钟周期。如果权重不能有效缓存,访存将成为主要瓶颈。使用 CMSIS-NN 的 im2col 变换或直接卷积优化,可以减少重复访存。

2.4 案例拆解:音频唤醒词检测的推理链路分析

以一个典型的语音唤醒词检测(KWS)任务为例,展示如何在真实场景中应用上述知识进行初步 profiling。

硬件平台:STM32L476(Cortex-M4 @80MHz,SRAM 128KB,Flash 1MB)
模型:DS-CNN(深度可分离卷积网络),输入 49×10 MFCC 特征,10 个类别,模型大小 42KB,量化 int8。
目标:推理耗时 < 100ms,功耗 < 5mW。

初始现象:实测推理耗时 320ms,远超目标。使用 GPIO 翻转法测量各阶段耗时:

阶段 耗时(ms) 占比 初步判断
MFCC 特征提取 45 14% 浮点 FFT 计算过慢
模型加载(一次性) 12 — 可接受,但可优化
第一层 Conv2D 98 31% 标准卷积,计算量大
后续 DepthwiseConv2D 120 38% 权重从 Flash 读取频繁
全连接 + Softmax 35 11% Softmax 的 exp 计算慢
后处理与输出 10 3% UART 发送耗时

分析过程:

  1. MFCC 提取使用浮点 FFT,在无 FPU 的 M4 上需要软件浮点模拟,耗时严重。改为定点 FFT(如 CMSIS-DSP 的 q15 版本)后,耗时降至 18ms。
  2. 第一层 Conv2D 输入通道为 10,输出通道为 64,使用标准卷积。改为 DepthwiseConv2D + PointwiseConv2D 结构,计算量降低约 60%,耗时降至 40ms。
  3. 后续 DepthwiseConv2D 的权重为 int8 格式,但未使用 CMSIS-NN 的优化内核。改用 arm_depthwise_conv_s8 后,利用 SIMD 指令,耗时从 120ms 降至 55ms。
  4. Softmax 使用查表法替代 exp 计算,耗时从 35ms 降至 8ms。

优化后结果:总推理耗时 320ms → 121ms,进一步将 CPU 主频提升至 100MHz(功耗增加 0.8mW),最终耗时 96ms,满足目标。

风险与代价:定点 FFT 引入约 0.5% 精度损失;模型结构修改需要重新训练验证;CMSIS-NN 内核要求 4 字节对齐,增加了内存管理复杂度。

复盘经验:推理耗时往往不是均匀分布的,而是集中在少数几个热点算子。通过阶段拆分,可以快速定位瓶颈,避免盲目优化整个模型。同时,硬件特性(如 FPU 有无、SIMD 支持)对优化路径选择有决定性影响。

2.5 常见误区与总结

在 TinyML profiling 实践中,以下误区需要特别警惕:

  • 误区一:只测总耗时,不拆阶段。总耗时只能反映整体性能,无法指导优化。必须拆分到算子级别甚至循环级别。
  • 误区二:忽略编译优化选项。使用 -O0 编译的代码可能比 -O2 慢 3~5 倍。Profiling 必须在最终发布配置下进行。
  • 误区三:未考虑中断影响。RTOS 的定时器中断、外设中断可能打断推理过程,导致耗时抖动。需要统计最坏情况执行时间(WCET)。
  • 误区四:混淆 Flash 和 RAM 访问速度。Flash 读取通常需要等待状态(wait states),在高速 MCU 上可能成为瓶颈。
  • 误区五:忽略量化影响。int8 量化推理虽然计算更快,但反量化(dequantize)和再量化(requantize)操作可能引入额外开销,需要单独 profiling。