阿里巴巴推斷框架MNN在iOS上的使用小結

MNN介紹

端側智能現在已經不是新鮮話題,不管是從數據安全出發,還是從實時性能考慮,端側深度學習算法推理都有其不可替代的優勢。之前已經有一段時間的端側推理框架熱潮,google、Facebook、百度、騰訊、小米以及一些名氣不大但是實力很強的小公司,都開源了自家的端側推理框架,阿里MNN在18年年底開源,有後來居上的趨勢和決心,不僅工程結構的完備性和規範性很好,開發團隊和應用場景也有一定的優勢。

MNN是一個輕量級的深度神經網絡推理引擎,在端側加載深度神經網絡模型進行推理預測。目前,MNN已經在阿里巴巴的手機淘寶、手機天貓、優酷等20多個App中使用,覆蓋直播、短視頻、搜索推薦、商品圖像搜索、互動營銷、權益發放、安全風控等場景。此外,IoT等場景下也有若干應用。

目的

之前在兩個手機上跑了一下MNN的benchmark,結果如下
[外鏈圖片轉存失敗(img-amoWAQfw-1562123546316)(evernotecid://1CA468D3-8108-4F95-9FF0-B3384CD16BE9/appyinxiangcom/22266324/ENResource/p285)]
CPU優化的效率看着還是蠻喜人的。

作爲應用開發者,我們對常用的前端框架做了一個封裝,包括coreml、NCNN、MACE等,統一接口輸入和輸出,以及cvtColor、rotate、resize等CV操作。在iOS上,我們自身模型使用ncnn的性能並不能令人滿意,在看到MNN之後,就想把MNN也加到我們的統一推斷框架中,來提升性能。

編譯

相比較Android的CMake+NDK交叉編譯,iOS上MNN提供了完整的Xcode工程,非常方便
在這裏插入圖片描述
或者跑demo工程
在這裏插入圖片描述
完整的demo工程如下:
在這裏插入圖片描述

編譯結果

使用project/ios編譯出來的MNN.framework,大小6.4M:
在這裏插入圖片描述

使用demo的playground編譯出來的libMNN.a,大小5.6M,mnn.metallib 583kb:
在這裏插入圖片描述

使用

在我們的工程中添加MNN頭文件和庫,就可以像demo中一樣使用MNN的功能,我們主要用到了一下幾個功能:

基本對象

std::shared_ptr<MNN::Interpreter> _net  = MNN::Interpreter::createFromFile(model.UTF8String);;
MNN::Session *_session = _net->createSession(config);;
MNN::CV::ImageProcess *_process;

_net包括網絡信息,類似NCNN的Net對象,_session處理會話,類似NCNN的Extractor對象,_process負責處理圖像。

圖像預處理

MNN提供了很完整的圖像預處理方法,包含在core/cv目錄下,主要接口是

auto pretreat = std::shared_ptr<MNN::CV::ImageProcess>(
        MNN::CV::ImageProcess::create(MNN::CV::RGBA, MNN::CV::BGR, means, 3, normals, 3));
auto input = _net->getSessionInput(_session, nullptr);
pretreat->convert(rgba, w, h, 0, input);

先傳入一系列參數,創建一個MNN::CV::ImageProcess對象或指針
在這裏插入圖片描述
在這裏插入圖片描述
然後使用MNN::CV::ImageProcess的convert方法來對圖像進行處理
在這裏插入圖片描述

也可以通過構造一個ImageProcess::Config變量
在這裏插入圖片描述
然後通過
在這裏插入圖片描述
來構造ImageProcess對象。

cvtColor

通過ImageProcess的create構造函數參數來解決,第一個參數是待處理圖像的格式,第二個是目標格式。

resize

需要設置一個matrix

MNN::CV::Matrix matrix;
matrix.postScale((w - 1) / 223.0, (h - 1) / 223.0);
pretreat->setMatrix(matrix);

其中w是輸入圖像的寬,h是高,第一個223.0是模型input的寬-1,第二個是模型input的高-1,因爲這個模型輸入是224*224,所以兩個都是223.0.

需要注意的是,如果不需要resize,則調用matrix.poseScale(1.0,1.0)

歸一化

構造means和norms

const float means[3]   = {103.94f, 116.78f, 123.68f};
const float normals[3] = {0.017f, 0.017f, 0.017f};

和cvtColor一樣,當做ImageProcess的構造參數傳入。

如果不需要歸一化,可以將means都設爲0,normals爲1.0

RUN

_net->runSession(_session);

這個接口足夠簡潔。

輸出

在這裏插入圖片描述
拿到float *data指針,也就成功了一大半,爲什麼說是一大半而不是全部呢?以爲這裏還有一個非常重要的環節:數據排布,經過不完全測試,得到一個結論,MNN的輸出排布是NCHW。

測試結果

在鋪墊了那麼多之後,發現測試結果並不理想,我們只對純CPU做了測試,並與coreml做了對比:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章