操指南)
ONNX Runtime3步在Android和iOS跑通AI模型推理的實(shí)操指南【免費(fèi)下載鏈接】onnxruntimeONNX Runtime: cross-platform, high performance ML inferencing and training accelerator項(xiàng)目地址: https://gitcode.com/GitHub_Trending/on/onnxruntime假設(shè)我們要給一個(gè)拍照應(yīng)用加上圖片識(shí)別能力但又不想讓用戶等200ms以上。這里要用到的工具是ONNX Runtime模型訓(xùn)練好之后導(dǎo)出成ONNX格式一次導(dǎo)出Android和iOS兩端原生跑通。這篇文章記錄我們完整走一遍移動(dòng)部署的流程——裝依賴、建會(huì)話、出推理結(jié)果。它到底解決什么問(wèn)題一句話ONNX Runtime就像一個(gè)多語(yǔ)言翻譯官把PyTorch/TensorFlow導(dǎo)出的模型統(tǒng)一翻譯成手機(jī)硬件能直接執(zhí)行的指令。它內(nèi)部的核心概念是執(zhí)行提供器Execution Provider簡(jiǎn)稱EP每種硬件加速通道對(duì)應(yīng)一個(gè)EP比如Android上的NNAPI、iOS上的Core ML、以及通用的XNNPACK針對(duì)移動(dòng)CPU優(yōu)化過(guò)的內(nèi)核庫(kù)。創(chuàng)建會(huì)話時(shí)運(yùn)行時(shí)會(huì)自動(dòng)挑選支持模型算子的EP來(lái)執(zhí)行我們只需要聲明想用哪個(gè)剩下的交給框架。下圖是官方文檔里的執(zhí)行提供器架構(gòu)圖可以看到EP是掛在推理運(yùn)行時(shí)下面的一層同一套API對(duì)上層完全透明動(dòng)手前準(zhǔn)備 先確認(rèn)三樣?xùn)|西都很輕模型文件.onnx格式的模型比如MobileNetV2這類分類網(wǎng)絡(luò)大小通常幾MB到幾十MB。沒(méi)有現(xiàn)成的話用torch.onnx.export從PyTorch導(dǎo)出即可詳見(jiàn) docs/FAQ.md。開(kāi)發(fā)環(huán)境Android端用Android StudioJava 11及以上iOS端用Xcode CocoaPodsORT版本與倉(cāng)庫(kù)根目錄的VERSION_NUMBER當(dāng)前為1.30.0保持一致。依賴安裝// app/build.gradleAndroid端依賴 implementation com.microsoft.onnxruntime:onnxruntime-android:1.30.0# PodfileiOS端依賴 pod ONNXRuntime門(mén)檻到這里就算過(guò)了接下來(lái)是最核心的代碼部分。3步跑通第一個(gè)demo步驟1創(chuàng)建環(huán)境與SessionOptions做什么初始化全局環(huán)境配置會(huì)話參數(shù)。// 環(huán)境與會(huì)話選項(xiàng)建議放在App啟動(dòng)時(shí)一次性完成 OrtEnvironment env OrtEnvironment.getEnvironment(); // 全局單例 OrtSession.SessionOptions options new OrtSession.SessionOptions(); options.addExecutionProvider( List.of(new OrtEpDevice(OrtProvider.NNAPI)), Map.of()); // 關(guān)鍵聲明優(yōu)先用NNAPI加速怎么驗(yàn)證env.getAvailableProviders()返回的列表里包含NnapiExecutionProvider說(shuō)明這個(gè)EP在當(dāng)前構(gòu)建里可用。步驟2加載模型構(gòu)建輸入張量做什么把ONNX文件加載成會(huì)話把預(yù)處理好的圖像數(shù)據(jù)包成輸入張量。// 從assets讀模型并創(chuàng)建會(huì)話 InputStream in getAssets().open(mobilenet_v2.onnx); byte[] model in.readAllBytes(); OrtSession session env.createSession(model, options); // 圖像預(yù)處理成float數(shù)組224x224x3轉(zhuǎn)成NCHW布局 float[] pixels preprocessImage(bitmap); // ... 省略歸一化等細(xì)節(jié) long[] shape {1, 3, 224, 224}; OnnxTensor input OnnxTensor.createTensor(env, pixels, shape);怎么驗(yàn)證session創(chuàng)建成功且不拋OrtException說(shuō)明模型圖解析、算子匹配都通過(guò)了。步驟3執(zhí)行推理并讀結(jié)果做什么按名字傳入輸入張量拿到輸出并解析。MapString, OnnxTensor inputs Map.of(input, input); // key必須是模型定義的輸入名 OrtSession.Result outputs session.run(inputs); float[] scores (float[]) outputs.get(0).getValue(); outputs.close(); int topClass argmax(scores); // 找到概率最高的類別怎么驗(yàn)證topClass對(duì)著一張貓的照片應(yīng)該穩(wěn)定落在貓對(duì)應(yīng)的類別號(hào)上這就是最小閉環(huán)跑通了。兩端API同構(gòu)關(guān)鍵差異用這張表就夠了對(duì)比項(xiàng)AndroidiOS硬件加速EPOrtProvider.NNAPICore ML通過(guò)provider options配置模型放置src/main/assets打包進(jìn)APK拖進(jìn)Xcode工程走Bundle推理接口OrtSession.run(Map)ObjCORTSession的runWithInputs:Swift直接可用底層實(shí)現(xiàn)java/src/main/java/ai/onnxruntime/OrtSession.javaobjectivec/include/ort_session.hiOS側(cè)大致長(zhǎng)這樣// 創(chuàng)建會(huì)話并啟用Core MLoptions里帶coreml版本等配置 NSError *error nil; ORTSession *session [[ORTSession alloc] initWithEnvironment:env options:options handle:error]; // runWithInputs: 傳入ORTValueArray返回輸出邏輯與Java版run對(duì)應(yīng)讓它跑得快 ??環(huán)境這塊跑通了下面是收益最明顯的幾個(gè)調(diào)優(yōu)點(diǎn)算子內(nèi)線程數(shù)推理慢且CPU利用率低時(shí)把setIntraOpNumThreads設(shè)到接近物理核心數(shù)大模型時(shí)留1-2核給系統(tǒng)。// 通常設(shè)為CPU核心數(shù)或略少 options.setIntraOpNumThreads(4);確認(rèn)EP真的生效創(chuàng)建會(huì)話后打印日志確認(rèn)子圖被分配到NNAPI/Core ML而不是全部回落CPU回落了就先檢查算子覆蓋率。量化模型CPU推理瓶頸明顯時(shí)在PC端離線做INT8量化模型體積和內(nèi)存占用都會(huì)降下來(lái)# 倉(cāng)庫(kù)自帶工具生成QDQ格式量化模型 python -m onnxruntime.quantize \ --input mobilenet_v2.onnx \ --output mobilenet_v2_int8.onnx \ --quant_format QDQ --per_channel圖優(yōu)化保持默認(rèn)最高檔setOptimizationLevel默認(rèn)就是全部?jī)?yōu)化開(kāi)啟別誤關(guān)。下圖展示了圖優(yōu)化階段做的算子融合與常量折疊這就是同一個(gè)模型跑得快的主要來(lái)源踩坑記錄 癥狀創(chuàng)建NNAPI會(huì)話失敗或大量算子回落CPU。原因NNAPI支持的算子集合有限模型里有未覆蓋的算子。解法用NnapiFlags相關(guān)的provider options調(diào)整CPU回落策略配置細(xì)節(jié)見(jiàn) onnxruntime/core/providers/nnapi/。癥狀session.run拋異常提示輸入找不到。原因傳給run的key和模型定義的輸入名對(duì)不上。解法先通過(guò)會(huì)話的輸入信息ValueInfo/OnnxModelMetadata打印真實(shí)名字別手寫(xiě)。癥狀第一幀推理特別慢后面正常。原因首次執(zhí)行包含圖優(yōu)化、算子編譯和內(nèi)存分配。解法會(huì)話創(chuàng)建和首次預(yù)熱放在App啟動(dòng)階段做不要放在用戶點(diǎn)擊識(shí)別之后。癥狀加載大模型時(shí)OOM。原因權(quán)重本身大加上中間張量峰值內(nèi)存。解法優(yōu)先上量化模型內(nèi)存相關(guān)選項(xiàng)參考 docs/Memory_Optimizer.md。接下來(lái)可以學(xué)什么真機(jī)測(cè)試方法怎么把benchmark推到手機(jī)上跑見(jiàn) docs/Android_testing.md。移動(dòng)端CPU內(nèi)核XNNPACK背后的MLAS庫(kù)做了大量手工優(yōu)化源碼在 onnxruntime/core/mlas/適合想摳極限性能的人。EP算子支持范圍想知道某個(gè)EP到底支持哪些算子翻 docs/ContribOperators.md 和providers目錄。到這里一個(gè)能跑的最小閉環(huán)就搭完了剩下的就是按自己的模型和業(yè)務(wù)把線程數(shù)、量化格式、EP配置這幾個(gè)旋鈕調(diào)到位。【免費(fèi)下載鏈接】onnxruntimeONNX Runtime: cross-platform, high performance ML inferencing and training accelerator項(xiàng)目地址: https://gitcode.com/GitHub_Trending/on/onnxruntime創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考