溫故而知新,參考mentor睿昊學長(xhplus)和主管鋒偉(forwil)的專欄,記錄在商湯實習內容的總結和反思。希望商湯工具人組越來越nb!
什么是模型部署
經過大量的圖片進行訓練后,一個具有上億個參數的深度學習模型在測試集上達到的預定的精度,這時候老板們一定催着把這個模型上線/搭載到產品中 進行 驗證/售賣。模型部署就是完成深度學習算法產品化的最后一步。一個完美的模型部署工具/引擎,理應完成以下幾個功能:
- 跨平台:可跑在任何的硬件上,包括各類cpu/gpu/dsp/asic/fpga...
- 高效能:速度快、占用內存少...
- 保精度:產品精度與訓練精度保持一致、損失極少...
- 產品集成:滿足產品的各種用法,包括加密、批處理、reshape,甚至授權,可裁剪
- 訓練打通:與訓練生態打通,最好是訓練完成后,簡單命令直接導出
理想是美好的,現實往往很慘。理應把模型部署做的很好的源頭:pytorch、tensorflow 做得不盡人意,尤其體現在跨平台、高效能和產品集成上。猜測是因為G&F兩家的模型部署場景只有雲與端,雲側可以用暴力的serving API直接將單模型上線,端側似乎大家只關心手機,G家草草的搞個tensorflow-lite支持arm/ocl就完事了。
在這方面明顯國內的需求場景走的非常靠前:1、國產成熟的深度學習芯片大量覆蓋雲側和端側,端側需求除手機之外需求同樣十分旺盛。2、國內的算法精度/速度要求及其高,普通的單模型流程無法滿足。
現在是2020年,可以斷言的是,國內隨便一家做AI公司的部署系統,必定領先G家和F家好幾代,這是貴國產業軟件技術領先性上,非常難得的狀態。
怎么是多平台模型部署
多平台模型部署指的是將已經訓練收斂的模型,經過一系列工具,最終將模型運用在各式各樣的計算設備上。市面上所有雲端、邊緣的人臉特效、人臉驗證等功能,都是以此種模式運行,達到高性能、低延時。
商湯的研究課題包括:如何用一套架構支持各式各樣的計算設備,如何將算法的前處理和后處理囊括在部署流程中,如何在可編程設備上達到極致的計算性能等等。
怎么研究部署系統
研究模型部署最好的范本絕對是DL框架的老祖宗:caffe。幾乎所有的部署系統都深受caffe的影響。caffe提供了一個非常簡單的基於net to layer的范式,很好的建模了至少是CNN模型的運行環境。下圖展示一個caffe的架構示意圖:

caffe是一個非常簡單的執行引擎,在不考慮訓練的情況下。最大單位為Net,在Net之上定義了一個Layer Vector,通過從0到n遍歷layer,調用layer.forward,即可完成一次前饋。caffe有一些設計被其他框架大量的借鑒,比如基於layer的注冊器機制、基於blob的內存管理等等。來自騰訊的ncnn/featherCNN都是基於caffe架構演進過來的(都繼承了一些特性,修復了一些問題)。
但caffe的缺點同時也十分明顯,給大家留下了非常非常多優化空間,可以說修復這些缺點養活了國內大量的深度學習工程師:
- cuda default stream:caffe里沒有進行cuda kernel stream的管理,使得同一張顯卡跑兩個caffe部署任務效率急劇下降。
- Dtype:caffe里創建網絡的數值類型是通過模板參數傳入了,由於深度學習的低精度、低比特並不僅僅是改變編程語言里的數值類型這么簡單,導致至少在很長一段時間里,caffe甚至都極難支持fp16部署。
- protobuf:caffe極度依賴一個中心化的protobuf定義,這帶來了幾個問題,一是protobuf的代碼size不小,在極端追求庫體積情況下成為累贅。另一個是中心化的protobuf使得注冊一個新的layer及其不模塊化,很容易造成版本沖突。
- blob in layer:caffe的設計中,卷積的weight是隱藏在layer的參數中的,這樣的設計明顯不如將卷積的weight作為第二個/第三個常量tensor輸入來的簡潔和一致。
- heavey runtime:caffe沒有解耦 模型結構定義 與 layer kernel實現 兩者,使得caffe和protobuf格式深深的綁定在了一起。在深度學習不斷發展,硬件不斷變多,網絡格式日新月異的同時,all-in-one-runtime的方式制約了許多新feature的引入和更深的優化。compiler-runtime分離的方式被驗證是一種更合理的方案。
盡管如此,caffe依然是一個非常偉大的框架,任何在校生只要能把caffe吃透,對於其對深度學習的理解,大規模c++項目的認知將會上一個台階。
什么是深度學習芯片
深度學習芯片是一個並未界定嚴謹的概念。
狹義上,深度學習芯片指“針對深度學習設計的,可高效執行深度學習算法的芯片”,一般指ASIC和FPGA。其叫法五花八門,根據不同廠商的風格,有不同的特定稱呼,如DPU,NPU,TPU等等。
從廣義上,DSP、CPU和GPU也可以稱之為深度學習芯片,因為深度學習算法也可以極其高效的運行在這些設備上面:DSP往往擁有超長的指令集(VLIW),提供位寬特別大,峰值算力不錯的SIMD(單指令多數據流)指令支持。CPU中的ARM/X86同樣也為深度學習應用提供了長度128~256~512不等的fp32/fp16/int8計算。至於GPU,深度學習扛把子Nvidia的GPU就不同提了,移動端的GPU同樣提供豐富的矩陣算力,以fp16為主要支持的精度。
Hi3559A 提供了4種不同類型的深度學習執行方案
以最為典型的海思家族的Hi3559A SOC為例,就集結了四種典型的處理器類型。神奇的是,這四種處理器都可以執行深度學習模型,是不是很吃驚?所以如果聽到有人說“我這個算法可以跑在3559A”上,那你可得問清楚了是跑在哪個處理器,因為四種處理器的編程難度、算力可不相同。
芯片 | 算力 | 編程方法級別 |
---|---|---|
ARM A73/A53 | 28.8 + 19.2 Gops(fp32) | ARM neon:vmla |
Mali G71 | 約 22.16 Gops (fp16) | opencl 1.1/1.2/2.0 |
DSP:4 x cadence vp6 | 4 x 350 Gops (int8) | VP6 VLIW instruction |
NPU:2 x nnie11 | 2 x 1.7 Tops (int8) | HI_MPI_SVP_NNIE API |
部署框架如何支持一款新的深度學習硬件
我們可以找到非常方便的部署軟件庫:
- ARM:市面上支持arm上部署神經網絡的庫很多:ncnn,tnn,mnn,tengine,featherCNN,tvm
- DSP:tensilica官方提供運行庫XNNC(Xtensa Neural Network Compiler)看文檔有點麻煩,但跑起來應該沒問題。就是需要封裝到HI_SVP的DSP RPC接口中。
- NNIE:nnie的文檔十分完善,mapper一下直接量化部署全搞定!
“針對每個平台單獨轉換,執行的話,以后換新算法、新模型咋辦?以后如果又來一個新平台,你是不是還得再寫一遍代碼。”
——思考一種軟件架構,可以靈活的接入不同的新硬件,並且快速適配新模型:
定義一個標准接口(或者說基類),然后針對每個平台寫一個適配(子類)。實操上,可以使用工廠模式或者動態庫加載的方式,注冊到環境中。這樣就可以不用改動上層的前處理和后處理封裝,將神經網絡的執行過程完全隱藏在標准接口內了。幾個基礎函數如下:
1 nn_handle * NN_Init(char * model_file); // 通過模型文件創建句柄 2 void NN_Prepare(nn_handle * hdl); // 執行一的內存空間申請等事項 3 nn_tensor * NN_GetTensor(nn_handle * hdl, char * tensor_name); // 獲取輸入輸出Tensor 用於取數據(或者塞數據) 4 void NN_SetTensor(nn_handle * hdl, char * tensor_name, nn_tensor * tensor); // 將數據送回網絡(一般是輸入) 5 void NN_Forward(nn_handle * hdl): // 數據准備完畢,開始推理 6 void NN_Destroy(nn_handle * hdl); // 模型執行結束,銷毀句柄
一個簡單版本的多平台模型部署框架
除此之外,我們還發現另外一堆嚴重的問題:
- DSP和NNIE都只支持量化INT8/INT32數據輸入/輸出,之前Caffe和NCNN則都是fp32。數據類型無法統一。
- NNIE不支持在運行時使用caffe模型進行初始化,需要轉換到專用格式,這種格式只能在x86上進行。
- DSP的模型已經直接編譯成二進制固件了,需要非常復雜的DSP重啟操作才能使用。
- 刨掉Shufflenet不說,NNIE和DSP在Resnet18上因為將數值轉化成了INT8,都出現了不同程度的掉精度。
Reference
部署:深度學習落地的最后“N”公里