在Cortex-M上跑神经网络?这事我替你试过了

📅 2026/7/14 9:08:33
在Cortex-M上跑神经网络?这事我替你试过了
说实话三个月前有人跟我说在STM32上跑AI我第一反应是你认真的当时手头有个项目需要在产线终端做零件分类——不是识别车牌那种到处都是解决方案的活儿是区分流水线上三种长得几乎一样的金属零件。客户给的死命令不能上Linux板子不准走云服务预算只够用一颗STM32F407。这就很操蛋了。OpenMV那种玩具不够灵活。树莓派一颗CM4的价格比我整个BOM表还贵。那段时间我天天对着数据手册发呆。后来发现在MCU上跑推理这事儿其实已经有人在搞了而且搞得很深。先说说我踩的第一个坑——模型选型。我开始的想法特别天真找个现成的CNN转一下模型文件不就完了结果MobileNet v1在F407上胖到单次推理要十几秒而且编译完直接OOM。后来才搞明白在MCU上跑神经网络最要命的不是算力是那点可怜的SRAM——F4总共192KB中间特征图随便来几张就撑爆了。这是我最后定下来的配置// 最终在F407上跑通的TFLite Micro配置 // 输入: 96x96 灰度图int8量化 // 峰值RAM占用约82KB包含所有中间缓冲区 const tflite_micro_config_t cfg { .input_w 96, .input_h 96, .channels 1, .arena_size 100 * 1024, .num_threads 1 };对96x96灰度。我试过128x128彩色一张输入图就干进去49KB算一层卷积爆出来的中间结果直接HardFault。模型在PC上用Keras训练Converter量化成int8然后走xxd转成C数组嵌进固件。这套流程我折腾了快一个星期——shape不匹配arena size估不对量化参数传错每次报错都是个裸奔的HardFault全靠调试器看寄存器硬猜。然后说到CMSIS-NN。这东西是真香但接口也是真的劝退。// CMSIS-NN卷积加速调用示例 // 对比纯C实现快了约4.6倍 arm_status ret arm_convolve_s8(cparams, in_data, in_info, wt_data, wt_info, bias_data, bias_shifts, out_shifts, out_mult, out_offset, filter_offset, in_offset, act_min, act_max, (int16_t*)col_buf, out_data, out_info);光参数就十几个第一次对着文档数位置数得头皮发麻。但跑起来是真的爽——同一份模型没用CMSIS-NN之前推理一次340ms加上之后直接干到78msFPS从3蹦到12。对于区分三个零件来说绰绰有余。中间还翻了一次大车。Quantization-aware trainingQAT和Post-training quantizationPTQ我一开始觉得都是量化嘛差别能有多大结果PTQ出来的模型精度掉了8个点零件A和零件B彻底分不清了。换成QAT重训了一轮精度损失压到1.5%以内稳了。教训很明确边缘端部署千万别偷懒。走PTQ省的那点时间后面调模型调到怀疑人生。还有个事儿挺反直觉的——有人说F4带FPU跑AI有优势但其实模型量化为int8之后FPU基本在摸鱼。CMSIS-NN底层走的是ARM SIMD指令SADD16这类跟浮点单元半毛钱关系没有。所以M3和M4跑量化模型的速度差距并不大别被FPU忽悠了。一些真心话别一上来就想跑YOLO——你跑不动的。从MobileNet v1/v2或者TinyML的经典模型起步输入分辨率能压就压。96x96和128x128看起来没差多少中间内存翻了一倍Tensor Arena别靠猜。TFLite Micro有专门的calculator算这个如果项目排期紧试试ST的X-CUBE-AI。它能把Keras模型直接生成STM32工程CubeMX里点几下就行了买板子多关注SRAM大小。Flash再大中间特征图塞不下全白搭项目交工那天客户挺满意我在想——就这十几行C代码背后是三个月的弯路。值吗我觉得值。至少下次有人问我嵌入式AI能不能搞的时候我会说能搞。但你得先准备好踩坑。