mnn不是万能加速器,先看模型脾气
很多人第一次用mnn,会把它当成“换个推理框架就变快”的按钮。说实话,这个想法很危险。端侧速度慢,常见根因不是框架,而是模型结构太别扭:动态shape太多、后处理写在Python里、NMS没拆出来、输入分辨率硬顶到1080P。
我一般先做一件小事:把模型按真实输入跑20次,记录平均耗时、P95耗时和峰值内存。别只看单次最快值。比如检测模型平均28ms,P95飙到55ms,用户看到的就是卡顿,不是28ms。这个数字比宣传页上的benchmark有用得多。
mnn真正难的不是跑出demo,而是把模型稳稳塞进手机、盒子或工控板里。我做端侧推理这些年,见过太多人一上来盯着FPS,结果上线后发热、内存峰值、算子不支持轮流爆雷。想少踩坑,得先把模型转换、量化、后端选择和回归测试捋顺。
很多人第一次用mnn,会把它当成“换个推理框架就变快”的按钮。说实话,这个想法很危险。端侧速度慢,常见根因不是框架,而是模型结构太别扭:动态shape太多、后处理写在Python里、NMS没拆出来、输入分辨率硬顶到1080P。
我一般先做一件小事:把模型按真实输入跑20次,记录平均耗时、P95耗时和峰值内存。别只看单次最快值。比如检测模型平均28ms,P95飙到55ms,用户看到的就是卡顿,不是28ms。这个数字比宣传页上的benchmark有用得多。
转换前先把ONNX清干净。我的习惯是固定opset,导出静态输入尺寸,再用onnxsim过一遍。别把训练时的奇怪节点带进来,比如Dropout、训练专用Resize、没必要的Cast链。转换失败时别急着改源码,先用Netron看图,十分钟能省半天。
还有个老坑:精度不对不一定是量化害的。很多问题出在预处理。RGB和BGR反了、mean/std顺序错了、NHWC和NCHW没对齐,结果看起来像模型废了。上线前我会准备10张固定测试图,保存原始输入、预处理后tensor、输出top结果,换设备也拿这套比。
mnn做INT8量化挺实用,但别闭眼全量化。分类模型通常比较稳,检测、分割、关键点模型更容易掉点。尤其是小目标检测,置信度差0.03,业务侧可能就漏掉一堆框。
校准数据别随便抓100张就完事。我更愿意拿真实线上分布:白天、夜晚、逆光、模糊、空场景都要有。数量不用吓人,300到800张通常比“随机一万张干净图”靠谱。量化后别只看mAP,顺手看误检样本,很多坑藏在边界场景里。
Android上很多项目会直接开OpenCL,以为GPU肯定快。实际我见过不少中低端机,GPU首帧初始化要几百毫秒,连续跑还发热降频,十分钟后比CPU慢。短任务、低频调用、相机间歇识别,CPU反而更稳。
选后端别凭感觉。拿目标机测三组:冷启动首帧、连续100帧、发热5分钟后。线程数也别拉满,4核机器开4线程不一定赚,UI、相机、编码都在抢资源。我常从2线程开始试,找到耗时和温度的平衡点。
真正上线前,我会卡五个点:模型文件大小、首帧耗时、峰值内存、异常输入、版本回滚。模型从18MB降到7MB可能比再快3ms更值钱,因为很多设备下载失败、存储紧张、冷启动慢。
日志也要留细一点。至少打出模型版本、后端类型、线程数、输入尺寸、单次耗时。线上出问题时,你能直接判断是新模型慢、设备太弱,还是某个后端翻车。没有这些字段,排查只能靠猜。