前言
關(guān)于視覺(jué)算法部署及落地,知乎上有一個(gè)較為熱的話題。本文對(duì)相關(guān)回答等進(jìn)行了整理,供大家參考。
最近關(guān)注的一個(gè)知乎問(wèn)題:視覺(jué)算法的工業(yè)部署及落地方面的技術(shù)知識(shí),怎么學(xué)?
感覺(jué)落地這塊坑確實(shí)挺多,入職以來(lái)一直在做視覺(jué)算法落地這一塊的東西,感覺(jué)有必要系統(tǒng)的整理一些落地部署相關(guān)的資料。
鏈接:https://zhuanlan.zhihu.com/p/277522145
一、部署
1. 火星少女:在C++平臺(tái)上部署PyTorch模型流程+踩坑實(shí)錄
2. DanielTANG:利用LibTorch部署PyTorch模型
二、加速
1. TensorRT
有兩個(gè)比較優(yōu)秀的git:
onnx/onnx-tensorrtgithub.com/onnx/onnx-tensorrt
wang-xinyu/tensorrtxgithub.com/wang-xinyu/tensorrtx
1)伯恩legacy:如何使用TensorRT對(duì)訓(xùn)練好的PyTorch模型進(jìn)行加速?
2)阿里云云棲號(hào):高性能深度學(xué)習(xí)支持引擎實(shí)戰(zhàn)——TensorRT
3) xcyuyuyu:深度學(xué)習(xí)模型部署(1)-Pytorch轉(zhuǎn)TensorRT(C++版)
4)基于TensorRT量化部署YOLOV5s 4.0模型
5)基于TensorRT量化部署RepVGG模型
6)基于TensorRT完成NanoDet模型部署
2. OpenVINO
1)手把手教你使用OpenVINO部署NanoDet模型
2)OpenVINO部署Mask-RCNN實(shí)例分割網(wǎng)絡(luò)
3)OpenVINO2021.4+YOLOX目標(biāo)檢測(cè)模型部署測(cè)試
4)OpenVINO 頭部姿態(tài)評(píng)估網(wǎng)絡(luò)應(yīng)用演示
5)OpenVINO 基于人臉landmark檢測(cè)實(shí)現(xiàn)眼睛疲勞/睡意檢測(cè)
三、模型轉(zhuǎn)換
1. ONNX
1)ONNX初探
2)ONNX 再探
3)YOLOv5x6模型來(lái)了! 同樣支持CPU上ONNX部署與推理
相關(guān)回答2
視覺(jué)算法的工業(yè)部署和落地是沒(méi)有你想得那么容易的,dirty work(手寫(xiě)c++, cuda各種前后處理) 全靠你對(duì)于上層模型算法的理解,以及不同hardware backend設(shè)計(jì)的深刻認(rèn)知。如果要利用編譯技術(shù),你又得對(duì)深度學(xué)習(xí)編譯器中如何在design space中搜optim的值和手寫(xiě)template來(lái)達(dá)到半自動(dòng)優(yōu)化有很好的掌握,你才能真正把一個(gè)paper里吹的“天花亂墜”的model部署到一個(gè)理論算力能跟得上的設(shè)備上( 當(dāng)然,real-time和power是很重要的指標(biāo))
從工業(yè)界的角度想要快速出活,真正要自學(xué)的話:
深度學(xué)習(xí)框架方面,讀一讀caffe的源碼和設(shè)計(jì)理念,看看其中的cpu/gpu上的op是怎么寫(xiě)的。
深度學(xué)習(xí)編譯器方面,讀一讀tvm的源碼和設(shè)計(jì)理念,看看編譯器是怎么把一個(gè)dl model經(jīng)過(guò)relay IR 再到 tvm IR,再到不同backend的codegen。以及編譯器對(duì)計(jì)算圖的常見(jiàn)優(yōu)化(算子融合,data layout等)
深度學(xué)習(xí)模型部署方面,針對(duì)nvidia的gpu,看看cuda,tensorRT的document,自己嘗試著把一個(gè)檢測(cè)或者分割的模型部署到實(shí)驗(yàn)室的機(jī)器上。針對(duì)移動(dòng)端的cpu,gpu,看看mnn,學(xué)習(xí)下mnn的code design。很多非常好的profiling,可視化工具。針對(duì)fpga設(shè)備,可以看看hls,opencl,verilog。畢竟直接拿現(xiàn)成的tool把model中的op翻譯成hls,opencl代碼還不是非常高效,很多東西還是直接寫(xiě)HDL所帶來(lái)的speed up才更直接。這就和很多時(shí)候在arm架構(gòu)的cpu上去優(yōu)化算法,直接手寫(xiě)匯編所帶來(lái)的提升更加直接。
從提升自己內(nèi)功的角度來(lái)看,認(rèn)真啃好:“編譯器,計(jì)算機(jī)體系結(jié)構(gòu),并行計(jì)算,
編程語(yǔ)言設(shè)計(jì),計(jì)算機(jī)系統(tǒng),計(jì)算機(jī)網(wǎng)絡(luò),C++程序設(shè)計(jì)” 來(lái)說(shuō)是更好不過(guò)了。
當(dāng)然,一切的一切都得來(lái)源于你對(duì)上層DL算法都有了深入了解,知道每個(gè)layer是怎么跑的,輸入的feature和輸出的feature都是怎么存的,軟件和算法層面都經(jīng)歷過(guò)怎樣的加速,還有哪些加速是需要結(jié)合hardware來(lái)進(jìn)行co-design的,你才能更好地把模型中的不同layer合理高效地部署到不同的hardware上。
給個(gè)結(jié)論:如果要真正想習(xí)得視覺(jué)算法的部署和落地,最快捷的方法,首先你需要有一個(gè)極為嚴(yán)格經(jīng)常push你并且還活躍在代碼一線的leader,然后還得有一個(gè)特定的業(yè)務(wù)場(chǎng)景和急迫的ddl。
相關(guān)回答3
個(gè)人認(rèn)為算法部署落地這個(gè)方向是比較踏實(shí)務(wù)實(shí)的方向,相比“設(shè)計(jì)模型提出新算法”,對(duì)于咱們這種并不天賦異稟來(lái)說(shuō),只要你肯付出,收獲是肯定有的(不像設(shè)計(jì)模型,那些巧妙的結(jié)果設(shè)計(jì)不出來(lái)就是設(shè)計(jì)不出來(lái)你氣不氣)。其實(shí)算法部署也算是開(kāi)發(fā)了,不僅需要和訓(xùn)練好的模型打交道,有時(shí)候也會(huì)干一些粗活累活(也就是dirty work),自己用C++、cuda寫(xiě)算子(預(yù)處理、op、后處理等等)去實(shí)現(xiàn)一些獨(dú)特的算子。算法部署最常用的語(yǔ)言是啥,當(dāng)然是C++了,C++雖然復(fù)雜,但是由于優(yōu)異的性能和各種特性(類對(duì)象、元編程等),被很多推理框架作為backbone的語(yǔ)言。
如果你想要自學(xué)但不知道學(xué)哪個(gè),無(wú)從下手,哈哈恭喜你和當(dāng)初的我一毛一樣。不過(guò)你現(xiàn)在要是問(wèn),我還是不知道應(yīng)該跟你怎么說(shuō),因?yàn)椴渴鹇涞剡@方面你需要學(xué)習(xí)需要做的事情還是蠻多的。最好還是以項(xiàng)目作為驅(qū)動(dòng),或者找一些開(kāi)源的推理部署框架練練手,找一兩個(gè)開(kāi)源項(xiàng)目玩玩,找找感覺(jué),自己也就逐漸有方向了。
前面幾位大佬提到的NCNN(優(yōu)秀)、MNN(牛逼)等框架(還有很多框架這里不一一列舉了額),是針對(duì)移動(dòng)端進(jìn)行部署進(jìn)行優(yōu)化的推理引擎,對(duì)ARM核進(jìn)行了優(yōu)化,如果你想做和移動(dòng)端或者嵌入式端有關(guān)系的,可以看看這兩個(gè)框架的源碼,跑一兩個(gè)demo找找感覺(jué),另外還有Openvino和TensorRT,分別是對(duì)應(yīng)cpu和gpu端的首推框架(想詳細(xì)了解可以參考我之前的文章),可以找相關(guān)的項(xiàng)目去做做。
部署的流程一般就是:
訓(xùn)練一個(gè)模型,也可以是拿一個(gè)別人訓(xùn)練好的模型
針對(duì)不同平臺(tái)生成的模型進(jìn)行轉(zhuǎn)換,也就是俗稱的parse、convert,前端解釋器
針對(duì)轉(zhuǎn)化后的模型進(jìn)行優(yōu)化,這一步很重要,涉及到很多優(yōu)化的步驟
將轉(zhuǎn)化好的模型運(yùn)行在特定的平臺(tái)(嵌入端或者服務(wù)端)
需要掌握什么技術(shù),學(xué)好C++很重要,起碼能看懂各種關(guān)于部署精巧設(shè)計(jì)的框架(再列一遍:Caffe、libtorch、ncnn、mnn、tvm、openvino、tensorrt,不完全統(tǒng)計(jì),我就列過(guò)我用過(guò)的)。當(dāng)然并行計(jì)算編程語(yǔ)言也可以學(xué)一個(gè),針對(duì)不同的平臺(tái)而不同,可以先學(xué)學(xué)cuda,資料更多一些,熟悉熟悉并行計(jì)算的原理,對(duì)以后學(xué)習(xí)其他并行語(yǔ)言都有幫助。
部署和落地的重要性...當(dāng)然是很重要呃,對(duì)于硬件公司來(lái)說(shuō),需要將深度學(xué)習(xí)算法部署到性能低到離譜的開(kāi)發(fā)板上,因?yàn)槌杀灸苁【褪?,這時(shí)就需要部署了。在算法層面優(yōu)化模型是一方面,但更重要的是從底層優(yōu)化這個(gè)模型,這就涉及到部署落地方面的各個(gè)知識(shí)(手寫(xiě)匯編算子加速、算子融合等等);對(duì)于軟件公司來(lái)說(shuō),我們往往需要將算法運(yùn)行到服務(wù)器上,當(dāng)然服務(wù)器可以是布滿2080TI的高性能CPU機(jī)器,但是如果QPS請(qǐng)求足夠高的話,需要的服務(wù)器數(shù)量也是相當(dāng)之大的。這個(gè)要緊關(guān)頭,如果我們的模型運(yùn)行的足夠快...可以省機(jī)器又可以騰一些buffer上新模型豈不很爽,這個(gè)時(shí)候也就需要優(yōu)化模型了,其實(shí)優(yōu)化手段也都差不多,只不過(guò)平臺(tái)從arm等嵌入式端變?yōu)間pu等桌面端了。
系統(tǒng)的知識(shí)嘛,有是有,不過(guò)實(shí)際中都是用到啥再看啥,有項(xiàng)目在push你,個(gè)人建議直接上手項(xiàng)目,沒(méi)有自己找找,按需學(xué)習(xí)。
這里簡(jiǎn)單總結(jié)下可以選擇上手:
好用的開(kāi)源推理框架:caffe NCNN、MNN、TVM
好用的開(kāi)源推理框架:Openvino、TensorRT(infer不開(kāi)源)
好用的開(kāi)源服務(wù)器框架:triton-server
好用又不好用的編程語(yǔ)言:C++、CUDA、python
基礎(chǔ)知識(shí):計(jì)算機(jī)原理編譯原理等
最近在搞triton server,將TensorRT作為inference后qps很夸張(這個(gè)是服務(wù)端部署),有興趣可以找我一塊交流。
再補(bǔ)充一點(diǎn):之前沒(méi)有詳細(xì)提到TVM這個(gè)神奇的神經(jīng)網(wǎng)絡(luò)編譯器,TVM最近也增加了對(duì)TensorRT轉(zhuǎn)化的支持,可以無(wú)縫將relay的中間ir轉(zhuǎn)化為T(mén)ensorRT的算子op,從而實(shí)現(xiàn)兩者之間的轉(zhuǎn)換。
有關(guān)TVM可以看我之前的兩篇文章:
一步一步解讀神經(jīng)網(wǎng)絡(luò)編譯器TVM(一)——一個(gè)簡(jiǎn)單的例子
一步一步解讀神經(jīng)網(wǎng)絡(luò)編譯器TVM(二)——利用TVM完成C++端的部署
總之,如果想要好好學(xué)習(xí)落地部署這一類知識(shí),首先還是需要認(rèn)真閱讀一些優(yōu)秀的開(kāi)源框架的源碼,了解其工作原理和內(nèi)部實(shí)現(xiàn)。久而久之,慢慢嘗試,對(duì)于落地部署這一塊也就慢慢熟絡(luò)起來(lái)了。
相關(guān)回答4
這題我會(huì),上半年自己魔改了一個(gè)三維物體探測(cè)的網(wǎng)絡(luò),分別部署在了樹(shù)莓派,Xilinx的FPGA板和谷歌的USB加速器上(論文是沒(méi)有的,精度不好被斃了哈哈哈)。
這個(gè)方向還是很偏工程實(shí)踐的。不同的硬件都有各自的工具鏈,比如服務(wù)器上的TF serving,N卡的TensorRT,Xilinx的VitisAI,谷歌的TF Lite,跨平臺(tái)的TVM等等。做的時(shí)候很多時(shí)間都花在熟悉API上了。我是建議從最簡(jiǎn)單的TF Lite和TensorRT開(kāi)始,之后可以一通百通。另外C++以及編譯那一套技術(shù)得會(huì)。
個(gè)人感覺(jué)最大的困難一在工程優(yōu)化。量化壓縮如何做好,能不能剪枝,如何科學(xué)安排前處理,數(shù)據(jù)加載,推理,后處理的整個(gè)pipeline等等?,F(xiàn)在很多工具都自動(dòng)化了,但是需要人為干涉的地方還是很多。有時(shí)候還能整出玄學(xué)來(lái)。
二在那些硬件或工具鏈壓根就不支持的算子,典型的就是Faster-RCNN的RoI-Pooling。遇到這種東西要么改網(wǎng)絡(luò)(比如換成Yolo這種硬件友好的),要么硬著頭皮自己手寫(xiě)kernel,魔改框架(比如TensorRT允許你這么做,前提是會(huì)寫(xiě)CUDA),要么恥辱地在CPU上用C++實(shí)現(xiàn)。
我自己栽在第二個(gè)上了。點(diǎn)云處理上那些天馬行空的算子在設(shè)計(jì)的時(shí)候是不考慮硬件實(shí)現(xiàn)的,想部署在非CUDA硬件上簡(jiǎn)直搞死人。硬核的做法是在FPGA上手寫(xiě)IP Core,但是這條技能樹(shù)想點(diǎn)出來(lái)也太漫長(zhǎng)了。偷懶的做法就是丟一部分運(yùn)算去CPU。這樣你的數(shù)據(jù)就要在CPU和協(xié)處理器之間反復(fù)橫跳。然而把Pipeline切的太碎之后,一來(lái)影響速度,二來(lái)量化又怎么做才好呢……
所以除非工程能力很強(qiáng),為了避免頭禿,盡量不要碰那些稀奇古怪的自定義算子。卷積卷卷卷就好。遇到算子名字里帶deformable,dynamic,graph,point,spatial的,我勸你趕緊跑。
相關(guān)回答5
我是19年開(kāi)始逐漸接觸CV中的一些算法部署,在NCNN,TensorRT,OpenVINO,NNIE和華為Atlas系列的各個(gè)框架上都有一些部署經(jīng)歷。另外目前作為一個(gè)新的小型Pytorch推理框架MsnhNet的核心開(kāi)發(fā)者之一,感覺(jué)自己是比較適合回答這個(gè)問(wèn)題的。我個(gè)人將從兩個(gè)方面回答這個(gè)問(wèn)題,第一個(gè)是怎么學(xué)的問(wèn)題,第二個(gè)是怎么學(xué)得更好的問(wèn)題。
算法落地部署怎么學(xué)?
我這里就以Hisi 3519A嵌入式開(kāi)發(fā)版(AI硬件和工具鏈叫NNIE)為例,描述一下我的學(xué)習(xí)經(jīng)歷。
首先,拿到一塊開(kāi)發(fā)版我們做CV相關(guān)算法部署的人員最關(guān)注的應(yīng)該就是它的CPU以及AI硬件的浮點(diǎn)峰值,這可以讓我們后面在部署我們某個(gè)算法,某個(gè)網(wǎng)絡(luò)的時(shí)候做到心中有數(shù),具體怎么算或者怎么查看可以參考:高洋:浮點(diǎn)峰值那些事兒。實(shí)際上,各個(gè)廠家的開(kāi)發(fā)板都會(huì)提供對(duì)應(yīng)的工具鏈和一些Benchmark數(shù)據(jù)。例如最近接觸到的地平線旭日開(kāi)發(fā)板就提供了包括Mobilenetv1/2/3,Yolov3/4/5,F(xiàn)CN/SegNet等常見(jiàn)視覺(jué)場(chǎng)景用到的網(wǎng)絡(luò)的Benchmark數(shù)據(jù),通過(guò)這些數(shù)據(jù)我們可以清楚的看到對(duì)于某個(gè)分辨率的圖像跑特定網(wǎng)絡(luò)的fps以及內(nèi)存消耗等等。上面介紹的這些是我在拿到一個(gè)開(kāi)發(fā)板進(jìn)行部署之前關(guān)注的。
然后,在了解了硬件的一些關(guān)鍵信息之后,我們就可以花幾天熟悉一下開(kāi)發(fā)版對(duì)應(yīng)工具鏈(也就是開(kāi)發(fā)板的前向推理框架)和官方示例。一般來(lái)說(shuō)特定的開(kāi)發(fā)板使用廠商提供的推理框架性能應(yīng)該是最高的,因?yàn)樗炙鼈兊腁I芯片如NNIE一些通用框架(比如NCNN,MNN,Tegine等)是沒(méi)有相關(guān)的底層加速實(shí)現(xiàn)的,例如nvida的顯卡部署我們首選TensorRT,Intel的CPU首選OpenVINO,arm的cpu選NCNN或者M(jìn)NN。一般來(lái)說(shuō)特定開(kāi)發(fā)版官方示例都提供了一些經(jīng)典的視覺(jué)任務(wù)比如分類,檢測(cè)使用它們的工具鏈進(jìn)行部署的例子,我們要熟悉這些例子,特別關(guān)注一下如何Debug,內(nèi)存釋放等等。
再然后,我們就可以針對(duì)我們的某個(gè)任務(wù)在我們想要的硬件平臺(tái)進(jìn)行部署了。例如我要部署一個(gè)DeepSort框架到Hisi 3519A開(kāi)發(fā)板上,首先我要保證我能在CPU上正常運(yùn)行我們的DeepSort代碼。然后將我們的DeepSort代碼拆分成檢測(cè),Reid,卡爾曼濾波,幀匹配各個(gè)過(guò)程利用開(kāi)發(fā)版的推理框架分別編碼。我建議在部署一個(gè)工程的時(shí)候最好進(jìn)行子任務(wù)的拆分,因?yàn)檫@樣更容易讓我們編碼完成之后進(jìn)行Debug的時(shí)候更容易找到是哪部分出了問(wèn)題,不至于調(diào)試時(shí)長(zhǎng)時(shí)間卡頓,降低工作效率。
最后,在我們部署完一個(gè)工程或者視覺(jué)任務(wù)以后我們最好再評(píng)估一下我們的網(wǎng)絡(luò)耗時(shí)和Benchmark提供的數(shù)據(jù)是否能對(duì)應(yīng)上,如果我們的某個(gè)網(wǎng)絡(luò)性能明顯低于Benchmark數(shù)據(jù)需要查看是否AI硬件被使用了,是否網(wǎng)絡(luò)細(xì)節(jié)設(shè)計(jì)不合理等等。只有我們部署的項(xiàng)目的精度和速度在上線之后經(jīng)過(guò)了大量數(shù)據(jù)驗(yàn)證,我們才能算完成了一個(gè)部署任務(wù)。
所以,我將自己部署一個(gè)工程的思路分享出來(lái),這里面都是我認(rèn)為應(yīng)該學(xué)習(xí)的比較關(guān)鍵的點(diǎn)。希望能幫助到你。
參考文獻(xiàn)
[1]?https://zhuanlan.zhihu.com/p/277522145
[2]?https://www.zhihu.com/question/428800593
編輯:黃飛
評(píng)論