不加班的秘訣:如何通過AOE快速集成NCNN?

来源:https://www.cnblogs.com/didichuxing/archive/2019/11/22/11910831.html
-Advertisement-
Play Games

NCNN是騰訊開源的一個為手機端極致優化的高性能神經網路前向計算框架。在AOE開源工程里,我們提供了NCNN組件,下麵我們以SqueezeNet物體識別這個Sample為例,來講一講NCNN組件的設計和用法。 ...


作為我司頭髮儲量前三的程式員

始終仗著頭髮多奮鬥在加班的第一線

時時靈魂拷問自己

年輕人,你憑什麼不加班?

雖然我沒有女朋友
但是,我有代碼呀

但我不明白的是,隔壁工位那個,到崗比我遲,下班比我早,天天準點兒下班接女朋友,工作還完成的不錯的樣子,當然,頭髮也還不錯。除了長得比我顯老,難道他有什麼制勝法寶嗎?趁著午休,以一禮拜咖啡為代價,我偷師了他的制勝法寶。GET了秘訣,或許我也可以事業愛情雙豐收了。

 

直接集成NCNN的缺點

直接集成NCNN熬老少男顏哇,想當年我一邊淚流滿面地集成,一邊想用女友的SK2給自己的臉補補(不,你沒有,both SK2和女友)咋回事兒呢,為SqueezeNet接入NCNN,把相關的模型文件,NCNN的頭文件和庫,JNI調用,前處理和後處理相關業務邏輯等。把這些內容都放在SqueezeNet Sample工程里。這樣簡單直接的集成方法,問題也很明顯,和業務耦合比較多,不具有通用性,前處理後處理都和SqueezeNcnn這個Sample有關,不能很方便地提供給其他業務組件使用。深入思考一下,如果我們把AI業務,作為一個一個單獨的AI組件提供給業務的同學使用,會發生這樣的情況:

每個組件都要依賴和包含NCNN的庫,而且每個組件的開發同學,都要去熟悉NCNN的介面,寫C的調用代碼,寫JNI。所以我們很自然地會想到要提取一個NCNN的組件出來,提取以後呢長得順眼了很多,大概是這個樣子。

 

AOE SDK里的NCNN組件

有了AOE SDK,我也可以一頓操作猛如虎了!在AOE開源SDK里,我們提供了NCNN組件,下麵我們從4個方面來講一講NCNN組件:

      ●NCNN組件的設計

      ●對SqueezeNet Sample的改造

      ●應用如何接入NCNN組件

      ●對NCNN組件的一些思考

 

★ NCNN組件的設計

不懂NCNN的組件設計,即使一頓操作猛如虎,你可能最後也只有兩塊五。那它的組件是什麼嘞?NCNN組件的設計理念是組件里不包含具體的業務邏輯,只包含對NCNN介面的封裝和調用。具體的業務邏輯,由業務方在外部實現。在介面定義和設計上,我們參考了TF Lite的源碼和介面設計。目前提供的對外調用介面,長這個樣子:

// 載入模型和param
void loadModelAndParam(...)
// 初始化是否成功
boolean isLoadModelSuccess()
// 輸入rgba數據
void inputRgba(...)
// 進行推理
void run(...)
// 多輸入多輸出推理
void runForMultipleInputsOutputs(...)
// 得到推理結果
Tensor getOutputTensor(...)
// 關閉和清理記憶體
void close()

而機智騷年本人,用的是這個:

├── AndroidManifest.xml
├── cpp
│   └── ncnn
│       ├── c_api_internal.h
│       ├── include
│       ├── interpreter.cpp
│       ├── Interpreter.h
│       ├── jni_util.cpp
│       ├── jni_utils.h
│       ├── nativeinterpreterwrapper_jni.cpp
│       ├── nativeinterpreterwrapper_jni.h
│       ├── tensor_jni.cpp
│       └── tensor_jni.h
├── java
│   └── com
│       └── didi
│           └── aoe
│               └── runtime
│                   └── ncnn
│                       ├── Interpreter.java
│                       ├── NativeInterpreterWrapper.java
│                       └── Tensor.java
└── jniLibs
    ├── arm64-v8a
    │   └── libncnn.a
    └── armeabi-v7a
        └── libncnn.a

 

    ●Interpreter,提供給外部調用,提供模型載入,推理這些方法。

    ●NativeInterpreterWrapper是具體的實現類,裡面對native進行調用。

    ●Tensor,主要是一些數據和native層的交互。

 

AOE NCNN用的好,任務完成早,奧秘在此。

     ●支持多輸入多輸出。

     ●使用ByteBuffer來提升效率。

     ●使用Object作為輸入和輸出(實際支持了ByteBuffer和多維數組)。

 

光說不練假把式,AOE NCNN的實現過程,且聽我細細道來。

 

 如何支持多輸入多輸出

為了支持多輸入和多輸出,我們在Native層創建了一個Tensor對象的列表,每個Tensor對象里保存了相關的輸入和輸出數據。Native層的Tensor對象,通過tensor_jni提供給java層調用,java層維護這個指向native層tensor的“指針”地址。這樣在有多輸入和多輸出的時候,只要拿到這個列表裡的對應的Tensor,就可以就行數據的操作了。

 

 ByteBuffer的使用

ByteBuffer,位元組緩存區處理子節的,比傳統的數組的效率要高。
DirectByteBuffer,使用的是堆外記憶體,省去了數據到內核的拷貝,因此效率比用ByteBuffer要高。

 

當然ByteBuffer的使用方法不是我們要說的重點,我們說說使用了ByteBuffer以後,給我們帶來的好處:
1.介面里的位元組操作更加便捷,例如裡面的putInt,getInt,putFloat,getFloat,flip等一系列介面,可以很方便的對數據進行操作。
2.和native層做交互,使用DirectByteBuffer,提升了效率。我們可以簡單理解為java層和native層可以直接對一塊“共用”記憶體進行操作,減少了中間的位元組的拷貝過程。

 

 如何使用Object作為輸入和輸出
目前我們只支持了ByteBuffer和MultiDimensionalArray。在實際的操作過程中,如果是ByteBuffer,我們會判斷是否是direct buffer,來進行不同的讀寫操作。如果是MultiDimensionalArray,我們會根據不同的數據類型(例如int, float等),維度等,來對數據進行讀寫操作。

 

 對SqueezeNet Sample的改造

集成AOE NCNN組件以後,讓SqueezeNet依賴NCNN Module,SqueezeNet Sample裡面只包含了模型文件,前處理和後處理相關的業務邏輯,前處理和後處理可以用java,也可以用c來實現,由具體的業務實現來決定。新的代碼結構變得非常簡潔,目錄如下:

├── AndroidManifest.xml
├── assets
│   └── squeeze
│       ├── model.config
│       ├── squeezenet_v1.1.bin
│       ├── squeezenet_v1.1.id.h
│       ├── squeezenet_v1.1.param.bin
│       └── synset_words.txt
└── java
    └── com
        └── didi
            └── aoe
                └── features
                │       ├── squeezenet_v1.1.id.h
│       ├── squeezenet_v1.1.param.bin
│       └── synset_words.txt
└── java
    └── com
        └── didi  
         └── aoe
                └── features
                    └── squeeze
                        └── SqueezeInterpreter.java

↑ 本Sample也適用於其他的AI業務組件對NCNN組件的調用。

(牛逼就完事兒)

 應用如何接入NCNN組件

對NCNN組件的接入,有兩種方式

     ●直接接入

     

 ●通過AOE SDK接入

▲兩種接入方式比較:

不BATTLE了,我單方面宣佈,AOESDK完勝!

 

 對NCNN組件的總結和思考

通過對NCNN組件的封裝,現在業務集成NCNN更加快捷方便了。之前我們一個新的業務集成NCNN,可能需要半天到一天的時間。使用AOE NCNN組件以後,可能只需要1-2小時的時間。當然NCNN組件目前還存在很多不完善的地方,我們對NCNN還需要去加深學習和理解。後面會通過不斷的學習,持續的對NCNN組件進行改造和優化。

 - - - - - - - - - - - - - - - - - - - - - - - - - - - A o E - - - - - - -  - - - - - - - - - - - - - - - - - - - -

 

原創不易,歡迎打賞

                  https://github.com/didi/AoE←據說點了這裡的程式員們都準點下班了/


 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • webpack載入css文件及其配置 1. 當我們寫了幾個css文件之後如果想要引用到html中去的話我們最開始的方式就是通過link標簽將css文件導入進去,但是如果我們的css文件有很多的話,一個個的導入是不推薦的;而現在我們學了webpack,我們希望的是通過打包bundle.js文件,將所有 ...
  • webpack的基本使用 webpack的安裝 1. webpack的使用時需要藉助 node 的環境的 2. 在 node 中自動下載了 npm 這個包管理工具,之後的操作我們需要使用npm包管理工具進行相關操作 3. 我們需要打開終端(cmd)或者編譯器中的終端(我使用的vs code編譯器,使 ...
  • <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv ...
  • 效果 <style type="text/css"> span{ width:80px; height: 10px; display: inline-block; background: grey; margin-right: 3px; font-size: 18px; text-align: ce ...
  • 前端頁面的成功呈現,不僅要求在理想情況下沒問題,當一些後臺介面訪問異常、靜態文件獲取失敗時,仍然需要儘可能提供降級方案或給用戶良好的反饋,不至於整個頁面的奔潰。今天我將分享一些提高頁面健壯性的技巧。 異常處理 主要指數據類型。這種情況最常出現在讀取後臺數據的時候,尤其是需要取數組、對象等引用類型時, ...
  • 進度條 1 <style> 2 #progress{ 3 position: relative; 4 margin: auto; 5 top: 200px; 6 display: block; 7 width: 200px; 8 height: 20px; 9 border-style: dotte ...
  • 如果不知道 Jimu(積木) 是啥,請移步 ".Net Core 分散式微服務框架介紹 Jimu" 這次升級除了支持 .Net Core 3.0 還新增部分功能,如 REST, 鏈路跟蹤等,以下為詳細; 一、功能列表 | 功能 | 說明 |Jimu 1.0.0 | Jimu 0.6.0| | | | ...
  • 轉自:https://www.cnblogs.com/lidabo/p/9134174.html 此處僅供學習,版權屬原作者; 作為一個圖形圖像方向的研究生,我經常都在和 OpenGL 、OpenCV 等多種 C++ 庫打交道。這些庫遵循著不同的規則和用法;另外,為了讓自己的程式具有更多的交互能力, ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...