基於OpenGL ES 的深度學習框架編寫

2021-07-31 18:15:30 字數 3131 閱讀 6486

本文出自:

caffe-android-lib 目前應該是最便於整合使用的深度學習框架庫。 

tensorflow和mxnet據說也有對應的android庫,因時間原因暫未測試。 

cnndroid,**這個是用 

renderscript 作優化的深度學習框架,不過就**實現和實際測試結果來看,效能一般。

實現可實時、體積小、通用的深度學習**框架。

可實時比如實時摳人像這個case: 

對每一幀相機預覽產生的資料,系統將其對映為opengl 的乙個external texture,然後需要 計算出乙個 mask texture,與原先的texture作混合,顯示出來。如果mask texture 的計算在cpu上進行,則需要每幀先把 graphicbuffer 的資料拷貝出來,計算出mask後上傳到 mask texture 去,產生一來一回兩次額外拷貝。

本工程需要支援 caffe 產出的模型檔案,支援常見的網路如lenet、resnet等等。這個工作量包括編寫相應層的運算元,設計網路結構,解析caffe模型的引數等。 

所幸的是,目前在移動端做好深度學習的**就足夠了,相比於兼顧訓練的結構至少省去2/3的工作量。

gpu加速的api

運算的分配

cnndroid中僅用gpu加速卷積層的運算,其他還是由cpu+多執行緒執行。以前我們在早期作gpu加速的預研時,也有過類似的嘗試,但是資料傳輸和同步的效能消耗遠大於協同計算帶來的效能提公升。因此這個工程中,網路中的計算全部由gpu完成,避免資料在cpu和gpu之間反覆傳輸或同步。

另外,gpu驅動在申請記憶體(分配紋理所需要記憶體空間)的時間消耗在移動裝置端是不可忽略的,因此,不能在運算過程中臨時建立紋理或其他buffer,必須事先分配好。

優化注意點

1、向量化運算 

**時,我們輸入神經網路的資料可表示為 w∗

h∗d 的三維資料。我們將輸入資料用乙個rgba32f格式的3d紋理存維,由於每乙個畫素有4個數值,得到的紋理大小是w∗

h∗ce

il(d

4)。 

對於卷積層和內積層,我們把引數儲存為mat4的陣列,然後其計算就完全是vec4級的向量化運算。

2、合適的localsize設計 

與opencl不一樣,computer shader 必須手動指定 workgroup 的大小,並且指定執行的 workgroup 數量。這兩組維度,都是越大越好。 

local size 一般而言越大越好,但 computer shader 所需要的暫存器越多,local size 的最大值就越小,考慮到最耗時的卷積shader所能使用的local size 一般也就 64,保守起見都定為64(8乘8)。 

不能對齊的情況在shader中處理,比如下面的**:

void main()

}

3、適當地合併/去除layer 

如正則層可以直接和上一層合併(末尾加個max處理就行),dropout層可以直接丟棄。 

合併可以提公升效能(不過不會太多),但最重要的是減少了中間記憶體。

分為兩個子模組,引擎模組在客戶端上執行,工具模組用來轉換caffe的模型檔案。 

引擎模組

1、資料層 

image 為乙個rgba32f格式的2d array紋理,ssbo為一種vbo, 

全稱為gl_shader_storage_buffer,用於儲存自定義型別的資料(主要就是卷積層和內積層的引數)。 

program 為 著色器鏈結而成的 opengl program,netinfo 由 proto 定義,用於規定網路結構。 

在 shader 中,image 和 ssbo 示例如下:

layout(rgba32f, binding = 0) writeonly

uniform

highp

image2darray uoutput;//image

layout(rgba32f, binding = 1) readonly

uniform

highp

image2darray uinput;//image

layout(binding = 2) readonly buffer kernel ukernel;//ssbo

2、運算元層 

包括各類layer的實現,如卷積,正則,內積(全連線),softmax等。 

每乙個layer要負責申請自己的輸出記憶體(image)。

3、結構層 

根據 netinfo 的資訊,建立各類運算元並構成dag(有向無環圖),執行運算並輸出結果。

下圖是lenet的dag示例: 

工具模組

包括乙個結構轉換器、引數初始化和拷貝工具。拷貝工具是比較容易出錯的,因為卷積層和內積層的引數需要補零對齊及重排。

跟開源的 caffe-android-lib 對比 

caffe-android-lib 11m 

deeplearningogl 440k 

全自主開發的,毫無疑問要小很多很多。

oppo r9 (mt6755, gpu: mali-t860)上的測試結果: 

連續執行十次,去除第一次的結果(移動裝置上一般都是動態調頻的,第一次跑的時候cpu/gpu的頻率還沒調起來,會比較慢)。 

lenet 網路: 

caffe-android-lib:5.0~5.2ms(執行緒設為4) 

deeplearningogl:3.6-3.8 ms

較cpu版本(包含了neon與多執行緒優化)提公升了 50%左右的效率,已經大大超出預期了,在gpu更好的機器上(如mate8上)表現會更佳。 

相比於 cnndroid 更是好很多了。

人像摳圖的場景很流暢,且不需要隔幀計算。

基於深度學習的NER

命名實體識別 ner 是在自然語言處理中的乙個經典問題,其應用也極為廣泛。比如從一句話中識別出人名 地名,從電商的搜尋中識別出產品的名字,識別藥物名稱等等。傳統的公認比較好的處理演算法是條件隨機場 crf 它是一種判別式概率模型,是隨機場的一種,常用於標註或分析序列資料,如自然語言文字或是生物序列。...

opengles學習筆記

glsl語言裡面的attribute和uniform型別的變數,在程式中通過gles20.glgetattriblocation和gles20.glgetuniformlocation獲取,這裡獲取類似取到了他的位址一樣,就像是指標,然後在程式裡面可以通過指標改變這些變數的值,怎麼改變呢?1.通過g...

基於深度學習的目標跟蹤

基於深度學習的目標檢測 基於深度學習的目標檢測綜述 目標檢測演算法匯聚 目標檢測演算法總結 10行 實現目標檢測 深度學習目標檢測 綜述 作者的個人理解 一刀流 tensorflow實現的目標檢測 有github 目標檢測演算法簡介,都是文字 內容摘要 r cnn是region based conv...