點擊上方「AIWalker」,選擇加「星標」
精品乾貨,瞬時送達
本文轉載自:GiantPandaCV
最近這個問題在知乎比較火,這裡將本公眾號兩個作者的回答以文章的方式分享出來,希望對感興趣的讀者有幫助。
白神回答這幾天被華為的atlas板子折磨的夠嗆,加班之餘,寫點心得吧。
2017年:比你大一屆,本人也是20屆的渣渣碩士,剛剛上研的時候,和大多數「內捲兒」一樣,我也很幸運被老闆安排了「計算機視覺&圖像處理&模式識別」的研究方向。屁顛屁顛的開始看cvpr,iccv的paper。回想起過去,那時的我年幼無知,在地平線的一臺四卡伺服器上非root權限一步一步的裝好了caffe,開始跑起來了openpose的訓練,原本以為我的煉丹生涯就這樣正式開始了,沒想到怎麼都復現不到paper上的精度,當時對multi-scale的測試看半天還不懂怎麼回事。經常被leader push進度,真心覺得自己菜得扣腳,很多時候都想放棄煉丹。一步一步,在工業界,從單幀圖像上的目標檢測,語義分割,實例分割,到人體姿態估計。再遷移到視頻上的目標檢測,語義分割,關鍵點檢測。以及最後畢業論文的多目標跟蹤。算是把整個工業界能用的cv模型都摸了一遍,領域內的經典paper也能做到信手拈來?起碼,各種開源的檢測框架(商湯的mmdet, Facebook 最早的mask rcnn,detectron1 (caffe2), detectron2 (pytorch), gluonCV)都用過並完成了自定義的項目,其中的源碼也都是「隨心」看過一遍,但是自己太蠢了,寫不到這個水平的python和cuda代碼,以及每次用完,對很多細節的設計只能感慨作者的牛逼。
2018年:一個偶然的機會,我開始看mxnet的源碼(當時還是使用的symbol接口),看著看著,覺得這玩意和caffe代碼好像,很多地方都是從caffe那裡復用的,設計也比caffe靈活不少,畢竟粒度更細,安裝也更加友好。我一步一步的學習mxnet官網上放出來的所有有關framework設計的知識,包括從「怎樣設計一個高效的data loader」,「怎麼樣設計一個engine把框架中的所有組件schedule起來」,「以及怎麼樣更好的優化memory和減少數據IO」,「包括怎麼樣設計一套面向任何等級用戶都友好的API」。原本以為自己掌握了設計DL framework的大體奧義,發現還是想太多了,在面對讓自己從頭實現一個框架的時候,我也只會用python定義class 包來包去,性能什麼的就別說了,我的菜還是沒辦法改變,最終還是想自己的愚蠢低下了頭。。。
2019年:又一個偶然的機會,我開始在大洋彼岸某個村的CSL做summer research,項目的需求是為他們實驗室的一款深度學習編譯器(target為fpga)去寫一套opencl的backend。什麼是編譯器?什麼是backend?什麼是fpga?什麼是opencl?一連串的問題對傻逼的我來說,一切都是未知。扒開這套編譯器的codebase,我發現大部分代碼都是從tvm那裡借鑑來的, 於是,我又走上了tvm的學習之路,從tvm的design到完整的編譯flow,包括底層的c++到與上層的python交互,以及autoTVM(那會Ansor還沒出來)全部走了一遍。對於一個根本沒玩過硬體開發板的我,這一切在當時來看是非常困難的,還好實驗室有給力的Ph.D.們,在他們的配合下,我也成功把基於xilinx和intel fpga的opencl backend全部添加了上去。那會的我,覺得自己算是掌握了 編譯器的大體奧義。可最終我還是想自己的傻逼低下了頭,涉及到傳統編譯器中的llvm的設計,codegen的很多細節,我還是一無所知。。。回國後,又加入了某條的mlsys組繼續做編譯器,我隨後又在glow的基礎上,為硬體組的自研晶片MVP開發profile-guided的quantization工具鏈以及針對網絡的每個layer開發了方便debug的可視化工具。
2020年:又又一個偶然的機會,被安排到了一家創業公司做intern,剛剛入職第一天就要求在2080ti上去優化一個超分4k視頻。對於一行cuda代碼都沒寫過的我來說,那是不敢想像的,項目負責人每兩天催一次進度,連給我配tensorRT,學習如何寫高性能cuda代碼的機會都不給。我每天都活在自責與痛苦中,為什麼我這麼菜?這麼垃圾啊?待我整完了從pytorch模型到onnx模型轉換,再到trt的編譯,以及為各種不支持的operator寫完tensorRT的plugin,再到關於image的前後處理全部手寫cuda kernel去和opencv硬碰硬。遺憾的是,整個inference還是沒有跑起來,當我用盡了我當時力所能及的cuda的debug工具(cuda-gdb,cuda-memcheck,...)最終發現還是敗在了模型的多張幀輸入沒辦法做到CPU和GPU上的memory 對齊。就這次偶然的機會,我竟然學會了tensorRT的部署。仗著這個經驗,我又把組裡其他模型:OCR,簡化版超清視頻到TX2,NX,AGX,智能相機等設備上,用盡了各種能優化的框架ncnn,mnn (其中包括針對工業級的二階段的OCR模型,det用tensorRT,reg用mnn的vulkan後端聯合開多線程優化在TX2上達到real-time)也熟悉了很多不同的backend和指令集架構。原本以為,我已經掌握了深度學習CV模型落地的要領,直到這幾天接到了要在華為的atlas 500板子上部署算法團隊自己整的一套faster rcnn的二階段檢測模型以及tracking,幾乎所有套件都要從頭開始手寫c++(藉助FFmpeg對RTSP拉流,解碼,udp報文傳送,前處理,rpn生成proposals,proposal變anchor,anchor到bbox,kalman filter, hungary, track ID篩選 ...),我才發現自己的無知,模型部署真的是個大坑。
以上內容吹逼歸吹逼,且當個故事聽聽就好。
其實我想表達的是 視覺算法的工業部署和落地是沒有你想得那麼容易的,dirty work(手寫c++, cuda各種前後處理) 全靠你對於上層模型算法的理解,以及不同hardware backend設計的深刻認知。如果要利用編譯技術,你又得對深度學習編譯器中如何在design space中搜optim的值和手寫template來達到半自動優化有很好的掌握,你才能真正把一個paper裡吹的「天花亂墜」的model部署到一個理論算力能跟得上的設備上( 當然,real-time和power是很重要的指標)
從工業界的角度想要快速出活,真正要自學的話:
深度學習框架方面,讀一讀caffe的源碼和設計理念,看看其中的cpu/gpu上的op是怎麼寫的。深度學習編譯器方面,讀一讀tvm的源碼和設計理念,看看編譯器是怎麼把一個dl model經過relay IR 再到 tvm IR,再到不同backend的codegen。以及編譯器對計算圖的常見優化(算子融合,data layout等)深度學習模型部署方面,針對nvidia的gpu,看看cuda,tensorRT的document,自己嘗試著把一個檢測或者分割的模型部署到實驗室的機器上。針對移動端的cpu,gpu,看看mnn,學習下mnn的code design。很多非常好的profiling,可視化工具。針對fpga設備,可以看看hls,opencl,verilog。畢竟直接拿現成的tool把model中的op翻譯成hls,opencl代碼還不是非常高效,很多東西還是直接寫HDL所帶來的speed up才更直接。這就和很多時候在arm架構的cpu上去優化算法,直接手寫彙編所帶來的提升更加直接。從提升自己內功的角度來看,認真啃好:「編譯器,計算機體系結構,並行計算,程式語言設計,計算機系統,計算機網絡,C++程序設計」 來說是更好不過了。
當然,一切的一切都得來源於你對上層DL算法都有了深入了解,知道每個layer是怎麼跑的,輸入的feature和輸出的feature都是怎麼存的,軟體和算法層面都經歷過怎樣的加速,還有哪些加速是需要結合hardware來進行co-design的,你才能更好地把模型中的不同layer合理高效地部署到不同的hardware上。
給個結論:如果要真正想習得視覺算法的部署和落地,最快捷的方法,首先你需要有一個極為嚴格經常push你並且還活躍在代碼一線的leader,然後還得有一個特定的業務場景和急迫的ddl。
現在以intern的身份帶著一幫和我一樣啥都不會的老弟老妹們一起探索著模型編譯加速部署的大坑,歡迎加入我的打工人隊伍(思謀科技),私信我簡歷即可。
BBuf回答謝邀,我是19年開始逐漸接觸CV中的一些算法部署,在NCNN,TensorRT,OpenVINO,NNIE和華為Atlas系列的各個框架上都有一些部署經歷。另外目前作為一個新的小型Pytorch推理框架MsnhNet的核心開發者之一,感覺自己是比較適合回答這個問題的。我個人將從兩個方面回答這個問題,第一個是怎麼學的問題,第二個是怎麼學得更好的問題。
算法落地部署怎麼學?
我這裡就以Hisi 3519A嵌入式開發版(AI硬體和工具鏈叫NNIE)為例,描述一下我的學習經歷。
首先,拿到一塊開發版我們做CV相關算法部署的人員最關注的應該就是它的CPU以及AI硬體的浮點峰值,這可以讓我們後面在部署我們某個算法,某個網絡的時候做到心中有數,具體怎麼算或者怎麼查看可以參考:浮點峰值那些事 。實際上,各個廠家的開發板都會提供對應的工具鏈和一些Benchmark數據。例如最近接觸到的地平線旭日開發板就提供了包括Mobilenetv1/2/3,Yolov3/4/5,FCN/SegNet等常見視覺場景用到的網絡的Benchmark數據,通過這些數據我們可以清楚的看到對於某個解析度的圖像跑特定網絡的fps以及內存消耗等等。上面介紹的這些是我在拿到一個開發板進行部署之前關注的。
然後,在了解了硬體的一些關鍵信息之後,我們就可以花幾天熟悉一下開發版對應工具鏈(也就是開發板的前向推理框架)和官方示例。一般來說特定的開發板使用廠商提供的推理框架性能應該是最高的,因為他分它們的AI晶片如NNIE一些通用框架(比如NCNN,MNN,Tegine等)是沒有相關的底層加速實現的,例如nvida的顯卡部署我們首選TensorRT,Intel的CPU首選OpenVINO,arm的cpu選NCNN或者MNN。一般來說特定開發版官方示例都提供了一些經典的視覺任務比如分類,檢測使用它們的工具鏈進行部署的例子,我們要熟悉這些例子,特別關注一下如何Debug,內存釋放等等。
再然後,我們就可以針對我們的某個任務在我們想要的硬體平臺進行部署了。例如我要部署一個DeepSort框架到Hisi 3519A開發板上,首先我要保證我能在CPU上正常運行我們的DeepSort代碼。然後將我們的DeepSort代碼拆分成檢測,Reid,卡爾曼濾波,幀匹配各個過程利用開發版的推理框架分別編碼。我建議在部署一個工程的時候最好進行子任務的拆分,因為這樣更容易讓我們編碼完成之後進行Debug的時候更容易找到是哪部分出了問題,不至於調試時長時間卡頓,降低工作效率。
最後,在我們部署完一個工程或者視覺任務以後我們最好再評估一下我們的網絡耗時和Benchmark提供的數據是否能對應上,如果我們的某個網絡性能明顯低於Benchmark數據需要查看是否AI硬體被使用了,是否網絡細節設計不合理等等。只有我們部署的項目的精度和速度在上線之後經過了大量數據驗證,我們才能算完成了一個部署任務。
所以,我將自己部署一個工程的思路分享出來,這裡面都是我認為應該學習的比較關鍵的點。希望能幫助到你。
算法落地部署怎麼學得更好?
上面說了怎麼學,這個只是基於一些已有的開源推理框架或者開發板對應的工具鏈進行開發。如果你想學得更好,我就不班門弄斧了。如果感興趣可以搜索一下知乎的 AI移動端優化 這個專欄,從裡面圈圈蟲,章小龍,白牛,梁德澎等做優化部署的大佬們的文章可以看出,想要學得更好得嘗試自己去做一些算法優化的活。
因為,算法部署用到的各個框架的核心技術就是針對特定硬體平臺的底層優化,例如NCNN針對Arm平臺使用Neon彙編優化,針對X86使用SSE/AVX2優化,針對GPU使用Vulkan優化等等。當然我知道一個人的能力是有限的,如果你僅僅是感興趣而已,那麼你可以選擇只學習某個平臺比如Arm CPU的優化技術。
我也是處於一邊學,一邊做的狀態。個人認為NCNN是這個世界上最好的優化框架,如果你基礎已經夠了(例如你了解了Neon彙編,知道卷積的計算過程)可以參考NCNN源碼進行學習,如果你不太了解可以參考上面那個專欄或者在GiantPandaCV的AI移動端優化專欄學習一些基礎知識,先入門然後我們一起學得更好。
相關連結GiantPandaCV網站:http://www.giantpandacv.com/NCNN:https://github.com/Tencent/ncnnMNN:https://github.com/alibaba/MNNTengine:https://github.com/OAID/Tenginehttps://github.com/msnh2012/Msnhnet