4. STM32Cube.AI 模型分析:内存、算力与推理时间

模型训练完了,量化也做了,接下来就是最关键的一步——分析报告解读。这一步很多人会跳过,直接点“生成代码”。但我建议你,花 10 分钟仔细看看 Cube.AI 生成的报告。它能告诉你,这个模型在 MCU 上到底能不能跑,瓶颈在哪。

说白了,这份报告就是 MCU 部署的“体检单”。内存够不够?算力吃不吃得消?推理一次要多久?全写在这了。我刚开始用 Cube.AI 时,也吃过亏——模型在 PC 上跑得飞快,一部署到 STM32F4 上,直接内存溢出。后来才发现,报告里早就警告了。

4.1 模型内存占用分析

MCU 的内存是稀缺资源。STM32F4 系列通常只有 128KB~256KB RAM,F7/H7 系列能到 512KB~1MB。模型占了多少,心里得有数。

Cube.AI 报告会把内存占用拆成三块:

内存类型 说明 典型占比
Activations 中间激活值,运行时动态分配 最大的一块,通常占 60%~80%
Weights 模型权重,量化后固定存储 10%~30%,取决于模型大小
Code + Scratch 代码段 + 临时缓冲区 5%~15%

关键指标:报告里会给出 Total RAM 和 Total ROM。RAM 必须小于芯片 SRAM 大小,ROM 必须小于 Flash 大小。否则,部署必失败。

我记得有一次,一个 MobileNetV1 模型,量化后权重只有 80KB,但激活值飙到了 180KB。我用的 STM32F407 只有 192KB RAM,差点就超了。后来我把输入分辨率从 224x224 降到 160x160,激活值直接砍到 110KB,问题解决。

我的习惯:先看 Activations 大小。如果它超过芯片 RAM 的 70%,我就会考虑缩小输入尺寸,或者换更轻量的网络结构。别等到编译报错再回头。

4.2 MACs 计算:算力需求到底多大?

MACs(Multiply-Accumulate Operations)是衡量模型计算量的标准单位。一个 MAC 就是一次乘加操作。MCU 没有 GPU 那种并行能力,MACs 越高,推理越慢。

报告里会给出每层的 MACs 和总 MACs。我一般这样看:

  • 总 MACs < 10M:STM32F4 系列可以流畅运行,帧率 10~30 FPS
  • 总 MACs 10M~50M:需要 F7/H7 系列,或者开启硬件加速
  • 总 MACs > 50M:建议用 MPU 或 NPU,纯 MCU 跑会很吃力

举个例子。一个 3x3 卷积层,输入 32x32x16,输出 32x32x32,它的 MACs 怎么算?

MACs = 输出特征图尺寸 × 卷积核尺寸 × 输入通道 × 输出通道
     = (32 × 32) × (3 × 3) × 16 × 32
     = 1024 × 9 × 16 × 32
     = 4,718,592  ≈ 4.7M

嗯,这里要注意:MACs 和 FLOPs 不是一回事。一个 MAC 等于两次 FLOP(一次乘,一次加)。有些工具报告 FLOPs,数值会翻倍。看报告时先确认单位。

我曾经踩过的坑:有个项目用了 Depthwise 卷积,我以为 MACs 会很低。结果报告显示,Depthwise 层本身 MACs 确实低,但后面的 Pointwise 层(1x1 卷积)因为通道数多,MACs 反而成了瓶颈。所以,别只看总 MACs,要逐层分析。

4.3 推理时间预估:准不准?

Cube.AI 会基于芯片型号和主频,给出一个推理时间预估。这个值准不准?我的经验是:参考价值很大,但别全信。

为什么?因为预估模型用的是理想条件——内存无竞争、缓存全命中、中断不触发。实际跑起来,可能会有 20%~50% 的偏差。

报告里通常给出两种时间:

  • Cycle 数:纯 CPU 周期,不受主频影响,适合跨芯片对比
  • 毫秒数:基于主频换算,方便直观理解

我一般这样用:

  1. 先看 Cycle 数,除以芯片主频,得到理论时间
  2. 加上 30% 的余量,作为实际预期
  3. 如果这个时间还满足需求,那就放心部署
  4. 如果不满足,就得优化了

举个例子:报告显示推理需要 12M Cycles,芯片主频 168MHz。理论时间 = 12M / 168M ≈ 71ms。加上 30% 余量 ≈ 92ms。我的应用要求 100ms 以内,嗯,刚好卡线。实际测试下来是 88ms,跟预估很接近。

4.4 分析报告解读:逐块拆解

报告生成后,你会看到类似下面的结构。我带你逐块看:

+--------------------------------------------------+
|  STM32Cube.AI Analysis Report                     |
|  Model: my_model.tflite                           |
|  Target: STM32F746ZG (Cortex-M7, 216MHz)         |
+--------------------------------------------------+
|  Memory                                           |
|    - Activations: 92.3 KB                         |
|    - Weights: 45.6 KB                             |
|    - Total RAM: 137.9 KB                          |
|    - Total ROM: 45.6 KB                           |
+--------------------------------------------------+
|  Complexity                                       |
|    - Total MACs: 8.7 M                            |
|    - Total MAdd: 17.4 M                           |
|    - Top-1 layer: conv2d_3 (2.1 M MACs)           |
+--------------------------------------------------+
|  Timing (estimated)                               |
|    - Total cycles: 6,234,567                      |
|    - Estimated time: 28.9 ms                      |
|    - Per-layer breakdown available                |
+--------------------------------------------------+

重点看三块:

  • Memory:确认 RAM 和 ROM 不超限。如果超了,优先减输入尺寸或量化
  • Complexity:找到 Top-1 层,那就是优化目标。我通常先看它是不是全连接层,是的话考虑替换成全局平均池化
  • Timing:看 Per-layer breakdown,找出最耗时的层。有时一个 5x5 卷积能占 40% 的时间,换成两个 3x3 就能大幅提速

我的习惯:把 Per-layer breakdown 导出成 CSV,在 Excel 里排序。一眼就能看到哪些层是“胖子”。先砍胖子,再考虑其他优化。

4.5 知识结构图:模型分析全流程

下面这张图总结了从拿到报告到最终决策的完整流程。你可以对照着看,自己现在处在哪一步。

模型分析全流程 模型分析报告解读流程 获取 Cube.AI 报告 检查内存占用 RAM 是否超限? 缩小输入 / 量化 或换轻量网络 分析 MACs 算力 逐层分析瓶颈 预估推理时间 决策:部署 / 优化 / 换芯片 💡 关键原则 先看内存,再看算力 逐层分析,找到瓶颈

4.6 实战建议:如何快速定位问题

拿到报告后,我一般按这个顺序排查:

  1. 看 Total RAM 是否超限——超了直接优化,不废话
  2. 看 Total MACs 是否在芯片能力范围内——超了考虑换芯片或剪枝
  3. 看 Per-layer breakdown,找 Top-3 耗时层——这些层就是优化重点
  4. 看是否有全连接层——全连接层是内存和算力大户,能换就换
  5. 看是否有大卷积核(5x5 以上)——拆成小卷积核通常能省 30%~50% 算力

我曾经遇到的一个案例:一个手势识别模型,报告显示 Total RAM 只有 80KB,但推理时间要 200ms。我一看 Per-layer breakdown,发现一个 7x7 卷积占了 60% 的时间。换成两个 3x3 卷积后,推理时间降到 90ms,精度只掉了 0.3%。这就是看报告的价值。