ONNX Runtime 移动端部署实战:跑通双端推理
ONNX Runtime 移动端部署实战跑通双端推理【免费下载链接】onnxruntimeONNX Runtime: cross-platform, high performance ML inferencing and training accelerator项目地址: https://gitcode.com/GitHub_Trending/on/onnxruntime把 ImageNet 分类模型塞进相册 App 做本地打标本质就是一次 ONNX Runtime 移动端部署一份.onnx文件同时面向 Android 与 iOS推理时再决定算力交给谁。咱们以让一个分类模型在两端跑起来为主线先弄懂它凭什么能跑再逐行跑通最后聊聊怎么调。图模型从训练框架导出到端侧推理的完整链路来源为本仓库docs/images/Mobile.png官方文档配图⚙️ 核心机制Execution Provider 如何屏蔽硬件差异ONNX Runtime 把在哪算抽象成了 Execution Provider执行提供器。模型加载后会被编译成计算图运行时按子图粒度做切分落在 NNAPIAndroid或 Core MLiOS能力范围内的算子被打包成子图交给对应硬件剩下的走 CPU 内核回退——这个切分由框架自动完成你在 Java/Swift 侧要做的只是注册一个 provider这一个配置动作。同一份推理代码因此可以横跨骁龙 NPU、Apple 的 ANE 和纯 CPU 设备硬件差异被压进了配置项里。图同一 ONNX Runtime 内核对接不同部署目标与硬件CPU/GPU/FPGA/NPU来源为本仓库docs/execution_providers/images/ONNX_Runtime_EP1.png移动端还有两个默认就生效的优化值得知道INT8/FP16 量化让权重和激活值的字节数减半乃至减为四分之一直接压缩模型体积与内存带宽占用——带宽在手机上往往比算力更先成为瓶颈ArenaAllocator 内存池则把推理过程中的中间张量分配收敛到预分配的内存池里避免高频malloc/free带来的碎片与抖动长会话推理时内存曲线会平稳得多。 两平台跑通指南Android 侧依赖用 Maven 坐标引入版本号以仓库根目录VERSION_NUMBER为准implementation com.microsoft.onnxruntime:onnxruntime-android:以VERSION_NUMBER为准推理主链路只有四步建环境、配 Session、构造张量、run。核心类 OrtSession 同时承载 SessionOptions 配置OrtEnvironment env OrtEnvironment.getEnvironment(); OrtSession.SessionOptions opts new OrtSession.SessionOptions(); opts.addExecutionProvider(OrtProvider.NNAPI); // 开启 NNAPI 加速 opts.setIntraOpNumThreads(4); // 线程数初值可取核心数一半 OrtSession session env.createSession(modelPath, opts); // 模型路径assets 读取逻辑略 long[] shape {1, 3, 224, 224}; try (OnnxTensor input OnnxTensor.createTensor(env, rgbFloats, shape); // 预处理浮点数据 OrtSession.Result result session.run(Map.of(input, input))) { float[] scores (float[]) result.get(0).getValue(); // 取置信度最高的标签 }NNAPI 执行提供器要求 Android 8.0API 27及以上低版本设备或不被支持的算子会自动回退 CPU真机/模拟器验证步骤可参考 docs/Android_testing.md。iOS 侧依赖走 CocoaPods版本同样以VERSION_NUMBER为准pod ONNXRuntimeObjective-C 层接口定义在 ort_session.hSwift 侧封装与其一一对应let env ORTEnv(loggingLevel: .warning) let opts ORTSessionOptions() try opts.appendExecutionProviderCoreML() // 开启 Core ML 执行提供器 let url Bundle.main.url(forResource: mobilenetv2, withExtension: onnx)! let session try ORTSession(env: env, modelURL: url, options: opts) let tensor try ORTValue.tensor(shape: [1, 3, 224, 224]) { ptr in // 预处理浮点数据 rgbFloats.withUnsafeBytes { ptr.update(from: $0) } } let out try session.run([session.inputNames![0]: tensor]) let scores try out[0].getDataAsTensor() // 解析输出得分Core ML 执行提供器有最低系统版本要求常见配置为 iOS 14provider 的可选参数与回退策略可查 coreml_execution_provider.h。 性能调优按影响从大到小拉三个杠杆杠杆一模型侧 INT8 量化效果权重/激活从 32 位压到 8 位体积与带宽开销显著下降是移动端通常收益最大的一步。操作用仓库自带量化工具跑一次静态量化用法详见 quantization 工具文档python -m onnxruntime.quantization.static_quantize_runner \ -i model.onnx -o model_quant.onnx --per_channel杠杆二线程数与算子并行效果大算子Conv、MatMul内部并行度直接决定单帧延迟的地板。操作setIntraOpNumThreads别照抄文档示例值以真机 2/4/8 各压测一轮取拐点opts.setIntraOpNumThreads(4); // 建议区间核心数 1/2 ~ 全核杠杆三输入/输出 Tensor 复用效果每帧省掉一次float[63504]量级的分配与拷贝对视频流场景的卡顿改善明显。操作初始化时创建一次推理时原地填充OnnxTensor input OnnxTensor.createTensor(env, buffer, shape); // 只建一次 input.copyFrom(newRgbFloats); // 每帧更新内容再 run✅ 上线前自查与排障模型 opset 版本与 runtime 支持范围是否匹配导出时锁定一个已验证的 opset输入 shape/数据类型与session.getInputNames声明是否严格一致尤其 NCHW 还是 NHWC内存峰值冷启动后连续推理 100 帧观察 native 堆是否单调上涨冷启动耗时模型加载 Session 构建耗时是否挤占首帧必要时后台预热NPU 回退行为抓一次 provider 日志确认子图切分比例而非注册成功就算上 NPU模型签名与完整性校验防止包内模型被替换排障一推理偶发 OOM 或被系统杀进程。定位路径用 Android Studio Profiler 或 Xcode 的 Memory 仪表看 native 段曲线若呈锯齿式爬升多半是中间张量没走内存池或每帧新建了大 Tensor。解决确认开启 arena 分配可参考 docs/Memory_Optimizer.md并落实上面杠杆三的 Tensor 复用。排障二日志显示 NNAPI/Core ML 注册成功但延迟没有下降。定位路径开启 graph 优化日志或 dump 优化后的计算图看 NPU 子图实际吞下了哪些算子——常见情况是 Conv 被融合进 NPU 子图但输出端的动态 shape 算子把子图打断了。解决固定输入 shape 重新导出模型或调整优化级别让框架做更激进的算子融合效果可对照下图的 basic/extended 两级差异图原始图、基础优化与扩展优化三级下的算子融合差异来源为本仓库docs/images/mnist_optimization.pngONNX Runtime 让一份模型、双端加速从口号变成几行配置的事。想继续深入建议看 samples/ 里的完整示例或 onnxruntime/python/tools/quantization/ 下的量化实战。【免费下载链接】onnxruntimeONNX Runtime: cross-platform, high performance ML inferencing and training accelerator项目地址: https://gitcode.com/GitHub_Trending/on/onnxruntime创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考