4、推理引擎选择:TFLite Micro、TensorRT、ONNX Runtime、NCNN、MNN的特点与选型对比
说到推理引擎选型,这其实是个老生常谈但又特别容易踩坑的话题。我见过不少团队,模型在PC上跑得飞快,一上嵌入式设备就崩了。说白了,选引擎就像选工具——没有最好的,只有最合适的。
今天咱们就把市面上主流的五个引擎掰开揉碎聊一聊。TFLite Micro、TensorRT、ONNX Runtime、NCNN、MNN,它们各自擅长什么?短板在哪?我结合自己踩过的坑,给你一份实在的选型指南。
4.1 五个引擎的定位与出身
先看一张总览表,心里有个底:
| 引擎 | 出身 | 主打场景 | 硬件支持 | 量化支持 |
|---|---|---|---|---|
| TFLite Micro | MCU、极低资源设备 | ARM Cortex-M、RISC-V | INT8量化为主 | |
| TensorRT | NVIDIA | GPU服务器、Jetson边缘 | NVIDIA GPU | FP16/INT8/INT4 |
| ONNX Runtime | Microsoft | 跨平台、多框架互转 | CPU/GPU/NPU | 动态量化、静态量化 |
| NCNN | 腾讯 | 移动端CPU/GPU | ARM、x86、Vulkan | FP16/INT8 |
| MNN | 阿里巴巴 | 移动端、IoT设备 | ARM、x86、OpenCL | FP16/INT8/混合精度 |
核心观点:选引擎的第一步,先看你的目标硬件。GPU平台无脑TensorRT,MCU平台只有TFLite Micro可选,移动端则在NCNN和MNN之间二选一。
4.2 TFLite Micro——MCU上的唯一选择
如果你做的是Cortex-M系列或者RISC-V的嵌入式开发,那TFLite Micro几乎是唯一成熟的方案。我最早接触它是在一个智能传感器项目上,Flash只有256KB,RAM只有64KB。当时试过其他引擎,编译完就超了。
TFLite Micro的核心思路是「极致精简」。它去掉了所有运行时动态分配,所有内存都在编译期确定。这意味着什么?你不用担心内存碎片,也不用怕堆溢出。
但代价也很明显——算子支持非常有限。我记得有一次想跑一个MobileNetV3,结果发现hard-swish算子不支持,只能手动改模型结构。嗯,这里要注意,如果你模型里用了比较新的算子,最好先查一下支持列表。
我的建议:MCU上做推理,尽量用老牌经典网络。比如MobileNetV1、SqueezeNet这些,算子兼容性好。非要上Transformer?那得做好手写算子的准备。
4.3 TensorRT——GPU上的性能之王
TensorRT,说白了就是NVIDIA给自家GPU做的「特调引擎」。它能把模型压到极致,FP16推理速度比原生PyTorch快3-5倍是常有的事。
我印象最深的一个项目,是在Jetson Nano上跑YOLOv5。直接用PyTorch推理,帧率只有8FPS。换成TensorRT,做了INT8量化,直接飙到30FPS。为什么会这样?因为TensorRT做了三件事:层融合、内存复用、量化校准。
不过TensorRT有个大坑——它只认自家格式。你得先把模型转成ONNX,再用TensorRT的解析器转成TRT引擎。这个过程中,算子兼容性问题特别多。我曾经花了两天时间,就为了修一个Resize算子的对齐方式。
避坑指南:我曾经在转ONNX时,因为PyTorch版本和ONNX opset版本不匹配,导致导出的模型推理结果全是NaN。后来养成了习惯:每次转模型前,先跑一遍onnxruntime验证精度。
4.4 ONNX Runtime——跨框架的「翻译官」
ONNX Runtime的定位很特别。它不追求极致性能,而是追求「什么都能跑」。你想想看,PyTorch训练的模型、TensorFlow训练的模型、甚至Caffe2的模型,都能通过ONNX格式统一到Runtime上推理。
我个人习惯把ONNX Runtime当作「精度验证工具」。每次做模型转换,先用ONNX Runtime跑一遍,确认精度没问题,再转到目标引擎。这样能快速定位问题出在转换环节还是推理环节。
但说实话,ONNX Runtime在嵌入式设备上的表现一般。它的内存占用偏大,启动速度也慢。我试过在树莓派上跑,同样的模型,NCNN比ONNX Runtime快30%左右。
4.5 NCNN——移动端的「老牌劲旅」
NCNN是腾讯开源的,在移动端推理引擎里算是元老级的存在。它的优势在于ARM CPU优化做得特别好,尤其是ARMv8.2架构下的半精度指令支持。
我记得有一次优化一个人脸检测模型,在骁龙865上,NCNN的FP16推理速度比MNN快了15%。但换到麒麟990上,结果又反过来了。这说明什么?引擎的优化和具体硬件绑定很深,不能只看纸面数据。
NCNN的另一个特点是「轻量」。编译后的库文件只有几百KB,非常适合集成到APK里。不过它的GPU支持比较弱,Vulkan后端还在完善中。
4.6 MNN——后起之秀的「全能选手」
MNN是阿里巴巴开源的,虽然比NCNN晚,但发展很快。它的设计思路是「一次转换,到处运行」。MNN有自己的模型格式,转换工具支持TensorFlow、PyTorch、ONNX等多种来源。
我比较欣赏MNN的一点是它的混合精度支持。你可以在同一个模型里,部分层用FP16,部分层用INT8。这在一些精度敏感的场景下特别有用。比如检测模型的最后几层用FP16,前面的特征提取层用INT8,精度损失能控制在1%以内。
不过MNN的文档质量嘛...嗯,说实话,有点一言难尽。有些API的注释还是英文的,而且示例代码不够全。我当初上手时,全靠读源码才搞明白一些配置参数的含义。
4.7 选型对比:一张表说清楚
| 对比维度 | TFLite Micro | TensorRT | ONNX Runtime | NCNN | MNN |
|---|---|---|---|---|---|
| 最低RAM需求 | ~10KB | ~512MB | ~100MB | ~10MB | ~10MB |
| 算子数量 | ~50个 | ~200个 | ~150个 | ~120个 | ~130个 |
| 量化工具链 | 完整 | 完整 | 一般 | 较完整 | 完整 |
| 社区活跃度 | 高 | 高 | 高 | 中 | 中 |
| 学习曲线 | 平缓 | 陡峭 | 平缓 | 中等 | 中等 |
选型口诀:MCU用TFLite Micro,GPU用TensorRT,跨平台验证用ONNX Runtime,移动端CPU优化选NCNN,需要混合精度或灵活部署选MNN。
4.8 我的实战建议
最后分享几个我自己的经验:
- 不要迷信基准测试。网上那些跑分数据,很多是在特定硬件、特定模型下测的。你实际部署时,一定要在自己的目标板上跑一遍。
- 量化是必选项。不管是INT8还是FP16,量化后推理速度能翻倍。我建议从FP16开始试,精度损失小,效果立竿见影。
- 做好算子兼容性检查。我吃过这个亏。模型在PC上跑得好好的,转到嵌入式设备上,发现某个算子不支持,只能重新训练模型。提前查算子支持列表,能省很多时间。
- 保留一个「安全网」。我的习惯是,每个模型都保留一份ONNX格式的副本。万一目标引擎出了问题,还能用ONNX Runtime快速验证。
好了,关于推理引擎的选型,今天就聊到这儿。下一章咱们会深入讲TFLite Micro的部署实战,包括模型转换、内存优化和性能调优。到时候我会拿一个实际项目来演示,敬请期待。