2019-06-28 TensorRT介紹(一)理論介紹

TensorRT理論介紹:基礎(chǔ)介紹TensorRT是什么;做了哪些優(yōu)化;為什么在有了框架的基礎(chǔ)上還需要TensorRT的優(yōu)化引擎

一、TensorRT理論解釋

TensorRT項(xiàng)目立項(xiàng)的時(shí)候名字叫做GPU Inference Engine(簡(jiǎn)稱GIE),Tensor表示數(shù)據(jù)流動(dòng)以張量的形式。所謂張量大家可以理解為更加復(fù)雜的高維數(shù)組,一般一維數(shù)組叫做Vector(即向量),二維數(shù)組叫做Matrix,再高緯度的就叫Tensor,Matrix其實(shí)是二維的Tensor。在TensoRT中,所有的數(shù)據(jù)都被組成最高四維的數(shù)組,如果對(duì)應(yīng)到CNN中其實(shí)就是{N, C, H, W},N表示batch size,即多少?gòu)垐D片或者多少個(gè)推斷(Inference)的實(shí)例;C表示channel數(shù)目;H和W表示圖像或feature maps的高度和寬度。TR表示的是Runtime。

下圖是NVDIA針對(duì)深度學(xué)習(xí)平臺(tái)的一系列完整的解決方案(官網(wǎng)有更新版本)。如果大家對(duì)深度學(xué)習(xí)有些了解的話可能會(huì)知道,它分為訓(xùn)練和部署兩部分,訓(xùn)練部分首先也是最重要的是構(gòu)建網(wǎng)絡(luò)結(jié)構(gòu),準(zhǔn)備數(shù)據(jù)集,使用各種框架進(jìn)行訓(xùn)練,訓(xùn)練要包含validation和test的過(guò)程,最后對(duì)于訓(xùn)練好的模型要在實(shí)際業(yè)務(wù)中進(jìn)行使用。訓(xùn)練的操作一般在線下,實(shí)時(shí)數(shù)據(jù)來(lái)之后在線訓(xùn)練的情況比較少,大多數(shù)情況下數(shù)據(jù)是離線的,已經(jīng)收集好的,數(shù)據(jù)更新不頻繁的一天或一周一收集,數(shù)據(jù)更新頻繁的可能幾十分鐘,在線下有大規(guī)模的集群開始對(duì)數(shù)據(jù)或模型進(jìn)行更新,這樣的訓(xùn)練需要消耗大量的GPU,相對(duì)而言一般會(huì)給一個(gè)比較大的batchsize,因?yàn)樗膶?shí)時(shí)性要求相對(duì)較低,一般訓(xùn)練模型給的是128,甚至有些極端的1024,大的batch的好處是可以充分的利用GPU設(shè)備。但是到推斷(Inference)的時(shí)候就是不同的概念了,推斷(Inference)的時(shí)候只需要做一個(gè)前向計(jì)算,將輸入通過(guò)神經(jīng)網(wǎng)絡(luò)得出預(yù)測(cè)的結(jié)果。而推斷(Inference)的實(shí)際部署有多種可能,可能部署在Data Center(云端數(shù)據(jù)中心),比如說(shuō)大家常見的手機(jī)上的語(yǔ)音輸入,目前都還是云端的,也就是說(shuō)你的聲音是傳到云端的,云端處理好之后把數(shù)據(jù)再返回來(lái);還可能部署在嵌入端,比如說(shuō)嵌入式的攝像頭、無(wú)人機(jī)、機(jī)器人或車載的自動(dòng)駕駛,當(dāng)然車載的自動(dòng)駕駛可能是嵌入式的設(shè)備,也可能是一臺(tái)完整的主機(jī),像這種嵌入式或自動(dòng)駕駛,它的特點(diǎn)是對(duì)實(shí)時(shí)性要求很高。同樣的,Data Center也是對(duì)實(shí)時(shí)性要求很高,做一個(gè)語(yǔ)音識(shí)別,不能說(shuō)說(shuō)完了等很長(zhǎng)時(shí)間還沒(méi)有返回,所以在線的部署最大的特點(diǎn)是對(duì)實(shí)時(shí)性要求很高,它對(duì)latency非常敏感,要我們能非常快的給出推斷(Inference)的結(jié)果。做一個(gè)不同恰當(dāng)?shù)谋确?,?xùn)練(Training)這個(gè)階段如果模型比較慢,其實(shí)是一個(gè)砸錢可以解決的問(wèn)題,我們可以用更大的集群、更多的機(jī)器,做更大的數(shù)據(jù)并行甚至是模型并行來(lái)訓(xùn)練它,重要的是成本的投入。而部署端不只是成本的問(wèn)題,如果方法不得當(dāng),即使使用目前最先進(jìn)的GPU,也無(wú)法滿足推斷(Inference)的實(shí)時(shí)性要求。因?yàn)槟P腿绻龅貌缓?,沒(méi)有做優(yōu)化,可能需要二三百毫秒才能做完一次推斷(Inference),再加上來(lái)回的網(wǎng)絡(luò)傳輸,用戶可能一秒后才能得到結(jié)果。在語(yǔ)音識(shí)別的場(chǎng)景之下,用戶可以等待;但是在駕駛的場(chǎng)景之下,可能會(huì)有性命之庾。



在部署階段,latency是非常重要的點(diǎn),而TensorRT是專門針對(duì)部署端進(jìn)行優(yōu)化的,目前TensorRT支持大部分主流的深度學(xué)習(xí)應(yīng)用,當(dāng)然最擅長(zhǎng)的是CNN(卷積神經(jīng)網(wǎng)絡(luò))領(lǐng)域,但是的TensorRT 3.0也是有RNN的API,也就是說(shuō)我們可以在里面做RNN的推斷(Inference)。



最典型的應(yīng)用是圖片的分類,這也是最經(jīng)典的,實(shí)際上也是深度學(xué)習(xí)目前解決的比較好的一些問(wèn)題。其他的例如,圖片的語(yǔ)義分割、目標(biāo)檢測(cè)等都是以圖片分類網(wǎng)絡(luò)為基礎(chǔ)進(jìn)行改進(jìn)的。目標(biāo)檢測(cè)是比較典型的例子(如下圖),訓(xùn)練(Training)是對(duì)已經(jīng)打好框的圖片進(jìn)行前向計(jì)算,得出的框和實(shí)際的框(ground truth)進(jìn)行對(duì)比,然后再做后向更新,更新模型。真正做推斷(Inference)的時(shí)候,比如一個(gè)攝像頭,基本上要保證是實(shí)時(shí)的,也就是說(shuō)起碼要保證每秒25-30幀的速度,鑒于實(shí)際應(yīng)用可能是二三十路攝像頭同時(shí)進(jìn)來(lái)的數(shù)據(jù),這時(shí)候必須保證一塊卡做到實(shí)時(shí)處理,還是比較有挑戰(zhàn)性的工作。

總結(jié)一下推斷(Inference)和訓(xùn)練(Training)的不同:

  1. 推斷(Inference)的網(wǎng)絡(luò)權(quán)值已經(jīng)固定下來(lái),無(wú)后向傳播過(guò)程,因此可以

1.1)模型固定,可以對(duì)計(jì)算圖進(jìn)行優(yōu)化

1.2 ) 輸入輸出大小固定,可以做memory優(yōu)化(注意:有一個(gè)概念是fine-tuning,即訓(xùn)練好的模型繼續(xù)調(diào)優(yōu),只是在已有的模型做小的改動(dòng),本質(zhì)上仍然是訓(xùn)練(Training)的過(guò)程,TensorRT沒(méi)有fine-tuning

  1. 推斷(Inference)的batch size要小很多,仍然是latency的問(wèn)題,因?yàn)槿绻鸼atch size很大,吞吐可以達(dá)到很大,比如每秒可以處理1024個(gè)batch,500毫秒處理完,吞吐可以達(dá)到2048,可以很好地利用GPU;但是推斷(Inference)不能做500毫秒處理,可以是8或者16,吞吐降低,沒(méi)有辦法很好地利用GPU.

  2. 推斷(Inference)可以使用低精度的技術(shù),訓(xùn)練的時(shí)候因?yàn)橐WC前后向傳播,每次梯度的更新是很微小的,這個(gè)時(shí)候需要相對(duì)較高的精度,一般來(lái)說(shuō)需要float型,如FP32,32位的浮點(diǎn)型來(lái)處理數(shù)據(jù),但是在推斷(Inference)的時(shí)候,對(duì)精度的要求沒(méi)有那么高,很多研究表明可以用低精度,如半長(zhǎng)(16)的float型,即FP16,也可以用8位的整型(INT8)來(lái)做推斷(Inference),研究結(jié)果表明沒(méi)有特別大的精度損失,尤其對(duì)CNN。更有甚者,對(duì)Binary(二進(jìn)制)的使用也處在研究過(guò)程中,即權(quán)值只有0和1。目前FP16和INT8的研究使用相對(duì)來(lái)說(shuō)比較成熟。低精度計(jì)算的好處是一方面可以減少計(jì)算量,原來(lái)計(jì)算32位的單元處理FP16的時(shí)候,理論上可以達(dá)到兩倍的速度,處理INT8的時(shí)候理論上可以達(dá)到四倍的速度。當(dāng)然會(huì)引入一些其他額外的操作,后面的講解中會(huì)詳細(xì)介紹FP18和INT8;另一方面是模型需要的空間減少,不管是權(quán)值的存儲(chǔ)還是中間值的存儲(chǔ),應(yīng)用更低的精度,模型大小會(huì)相應(yīng)減小。

下圖展示的是TensorRT的效果,當(dāng)然這是一個(gè)比較極端的例子,因?yàn)樵摾惺褂玫氖亲钕冗M(jìn)的GPU卡V100,V100添加了專門針對(duì)深度學(xué)習(xí)優(yōu)化的TensorCore,TensorCore可以完成4×4矩陣的半精度乘法,也就是可以完成一個(gè)4×4的FP16矩陣和另外一個(gè)4×4的FP16矩陣相乘,當(dāng)然可以再加一個(gè)矩陣(FP16 或FP32),得到一個(gè)FP32或者FP16的矩陣的過(guò)程。TensorCore在V100上理論峰值可以達(dá)到120 Tflops.(開個(gè)玩笑,電影終結(jié)者中整個(gè)天網(wǎng)的計(jì)算能力相當(dāng)于兩塊V100)?;氐綀D中,先看一下如果只是用CPU來(lái)做推斷(Inference),首先它的吞吐只能達(dá)到140,也就是說(shuō)每秒只能處理140張圖片,同時(shí)整個(gè)處理過(guò)程需要有14ms的延遲,也就是說(shuō)用戶提交請(qǐng)求后,推斷(Inference)階段最快需要14ms才能返回結(jié)果;如果使用V100,在TensorFlow中去做推斷(Inference),大概是6.67ms的延時(shí),但是吞吐只能達(dá)到305;如果使用V100加TensorRT,在保證延遲不變的情況下,吞吐可以提高15倍,高達(dá)5700張圖片每秒,這個(gè)差別是很大的。十幾倍的吞吐的提升實(shí)際上是在保證延遲的情況下成本的縮減 。



回到TensorRT的主題,之前大家普遍存在的一個(gè)疑問(wèn)是在訓(xùn)練過(guò)程中可以使用不同的框架,為什么推斷(Inference)不能用各種框架,比如TensorFlow等。當(dāng)然是可以用的,但是問(wèn)題是靈活性和性能是一種trade-off的關(guān)系,這是在做深度學(xué)習(xí)或訓(xùn)練過(guò)程中經(jīng)常會(huì)遇到的一個(gè)問(wèn)題。比如像TensorFlow的設(shè)計(jì)初衷是為各種各樣的操作來(lái)做準(zhǔn)備的,在早期的框架,例如Caffe中很多前后處理并不在框架里面完成,而是通過(guò)額外的程序或腳本處理,但是TensorFlow支持將所有的操作放入框架之中來(lái)完成,它提供了操作(Operation)級(jí)別的支持,使得靈活性大大提高,但是靈活性可能是以犧牲效率為代價(jià)的。TensorFlow在實(shí)現(xiàn)神經(jīng)網(wǎng)絡(luò)的過(guò)程中可以選擇各種各樣的高級(jí)庫(kù),如用nn來(lái)搭建,tf.nn中的convolution中可以加一個(gè)卷積,可以用slim來(lái)實(shí)現(xiàn)卷積,不同的卷積實(shí)現(xiàn)效果不同,但是其對(duì)計(jì)算圖和GPU都沒(méi)有做優(yōu)化,甚至在中間卷積算法的選擇上也沒(méi)有做優(yōu)化,而TensorRT在這方面做了很多工作。

在講TensorRT做了哪些優(yōu)化之前, 想介紹一下TensorRT的流程, 首先輸入是一個(gè)預(yù)先訓(xùn)練好的FP32的模型和網(wǎng)絡(luò),將模型通過(guò)parser等方式輸入到TensorRT中,TensorRT可以生成一個(gè)Serialization,也就是說(shuō)將輸入串流到內(nèi)存或文件中,形成一個(gè)優(yōu)化好的engine,執(zhí)行的時(shí)候可以調(diào)取它來(lái)執(zhí)行推斷(Inference)。



如上圖所示TensorRT整個(gè)過(guò)程可以分三個(gè)步驟,即模型的解析(Parser),Engine優(yōu)化和執(zhí)行(Execution)。暫時(shí)拋開TensorRT,如果讓大家從頭寫一個(gè)深度學(xué)習(xí)模型的前向過(guò)程,具體過(guò)程應(yīng)該是

  1. 首先實(shí)現(xiàn)NN的layer,如卷積的實(shí)現(xiàn),pooling的實(shí)現(xiàn)。

  2. 管理memory,數(shù)據(jù)在各層之間如何流動(dòng)。

  3. 推斷(Inference)的engine來(lái)調(diào)用各層的實(shí)現(xiàn)。

以上三個(gè)步驟在TendorRT都已經(jīng)實(shí)現(xiàn)好了,用戶需要做的是如何將網(wǎng)絡(luò)輸入到TensorRT中。目前TensorRT支持兩種輸入方式:

  1. 一種是Parser的方式,即模型解析器,輸入一個(gè)caffe的模型,可以解析出其中的網(wǎng)絡(luò)層及網(wǎng)絡(luò)層之間的連接關(guān)系,然后將其輸入到TensorRT中,但是TensorRT是如何知道這些連接關(guān)系呢?答案是API。

  2. API接口可以添加一個(gè)convolution或pooling。而Parser是解析模型文件,比如TensorFlow轉(zhuǎn)換成的uff,或者是caffe的模型,再用API添加到TensorRT中,構(gòu)建好網(wǎng)絡(luò)。構(gòu)建好后就可以做優(yōu)化。

? a) 考慮到一個(gè)情況,如果有一個(gè)網(wǎng)絡(luò)層不支持,這個(gè)有可能,TensorRT只支持主流的操作,比如說(shuō)一個(gè)神經(jīng)網(wǎng)絡(luò)專家開發(fā)了一個(gè)新的網(wǎng)絡(luò)層,新型卷積和以前的卷積都不一樣,TensorRT是不知道是做什么的。比如說(shuō)最常見的檢測(cè)網(wǎng)絡(luò),有一些網(wǎng)絡(luò)層也是不支持的,這個(gè)時(shí)候涉及到customer layer的功能,即用戶自定義層,構(gòu)建用戶自定義層需要告訴TensorRT該層的連接關(guān)系和實(shí)現(xiàn)方式,這樣TensorRT才能去做。

?b) 目前API支持兩種接口實(shí)現(xiàn)方式,一種是C++,另一種是Python,Python接口可能在一些快速實(shí)現(xiàn)上比較方便一些。

?c) Parser目前有三個(gè),一個(gè)是caffe Parser,這個(gè)是最古老的也是支持最完善的;另一個(gè)是uff,這個(gè)是NV定義的網(wǎng)絡(luò)模型的一種文件結(jié)構(gòu),現(xiàn)在TensorFlow可以直接轉(zhuǎn)成uff;另外下一個(gè)版本3.5或4.0會(huì)支持的onnx,是Facebook主導(dǎo)的開源的可交換的各個(gè)框架都可以輸出的,有點(diǎn)類似于文檔編輯中的word格式或AutoCAD中CAD的格式,雖然是由一個(gè)公司提出,但是有希望成為一個(gè)標(biāo)準(zhǔn),各個(gè)APP去支持這個(gè)標(biāo)準(zhǔn)。像pytorch和caffe 2都是支持這個(gè)格式的,這個(gè)目前只在NGC (NVDIA GPU Cloud)上支持,但是下一個(gè)版本發(fā)行都會(huì)支持。如果某個(gè)公司新推出一個(gè)特別火的框架不支持怎么辦,仍然可以采用API的方式,一層一層的添加進(jìn)去,告訴TensorRT連接關(guān)系,這也是OK的。

模型解析后,engine會(huì)進(jìn)行優(yōu)化,具體的優(yōu)化稍后會(huì)介紹。得到優(yōu)化好的engine可以序列化到內(nèi)存(buffer)或文件(file),讀的時(shí)候需要反序列化,將其變成engine以供使用。然后在執(zhí)行的時(shí)候創(chuàng)建context,主要是分配預(yù)先的資源,engine加context就可以做推斷(Inference)。

以上是TensorRT的整個(gè)過(guò)程,大家在疑惑TensorRT是否支持TensorFlow,首先大家寫的網(wǎng)絡(luò)計(jì)算層可能都是支持的,但是有些網(wǎng)絡(luò)層可能不支持,在不支持的情況下可以用customer layer的方式添加進(jìn)去,但是有時(shí)候?yàn)榱耸褂梅奖?,可能沒(méi)辦法一層一層的去添加,需要用模型文件形式,這個(gè)取決于Parser是否完全支持。相對(duì)而言,大家在框架有過(guò)比較后會(huì)發(fā)現(xiàn),caffe這個(gè)框架的特點(diǎn)是非常不靈活,如果要添加一個(gè)新的網(wǎng)絡(luò)層,需要修改源代碼;TensorFlow的優(yōu)點(diǎn)卻是非常的靈活。

剛才講到TensorRT所做的優(yōu)化,總結(jié)下來(lái)主要有這么幾點(diǎn):

第一,也是最重要的,它把一些網(wǎng)絡(luò)層進(jìn)行了合并。大家如果了解GPU的話會(huì)知道,在GPU上跑的函數(shù)叫Kernel,TensorRT是存在Kernel的調(diào)用的。在絕大部分框架中,比如一個(gè)卷積層、一個(gè)偏置層和一個(gè)reload層,這三層是需要調(diào)用三次cuDNN對(duì)應(yīng)的API,但實(shí)際上這三層的實(shí)現(xiàn)完全是可以合并到一起的,TensorRT會(huì)對(duì)一些可以合并網(wǎng)絡(luò)進(jìn)行合并;再比如說(shuō),目前的網(wǎng)絡(luò)一方面越來(lái)越深,另一方面越來(lái)越寬,可能并行做若干個(gè)相同大小的卷積,這些卷積計(jì)算其實(shí)也是可以合并到一起來(lái)做的。

第二,比如在concat這一層,比如說(shuō)這邊計(jì)算出來(lái)一個(gè)1×3×24×24,另一邊計(jì)算出來(lái)1×5×24×24,concat到一起,變成一個(gè)1×8×24×24的矩陣,這個(gè)叫concat這層這其實(shí)是完全沒(méi)有必要的,因?yàn)門ensorRT完全可以實(shí)現(xiàn)直接接到需要的地方,不用專門做concat的操作,所以這一層也可以取消掉。

第三,Kernel可以根據(jù)不同的batch size 大小和問(wèn)題的復(fù)雜程度,去選擇最合適的算法,TensorRT預(yù)先寫了很多GPU實(shí)現(xiàn),有一個(gè)自動(dòng)選擇的過(guò)程。

第四,不同的batch size會(huì)做tuning。

第五,不同的硬件如P4卡還是V100卡甚至是嵌入式設(shè)備的卡,TensorRT都會(huì)做優(yōu)化,得到優(yōu)化后的engine。

下圖是一個(gè)原始的GoogleNet的一部分,首先input后會(huì)有多個(gè)卷積,卷積完后有Bias和ReLU,結(jié)束后將結(jié)果concat(連接拼接)到一起,得到下一個(gè)input。

以上的整個(gè)過(guò)程可以做些什么優(yōu)化呢?首先是convolution, Bias和ReLU這三個(gè)操作可以合并成CBR,合并后的結(jié)果如下所示,其中包含四個(gè)1×1的CBR,一個(gè)3×3的CBR和一個(gè)5×5的CBR。

接下來(lái)可以繼續(xù)合并三個(gè)相連的1×1的CBR為一個(gè)大的1×1的CBR(如下圖),這個(gè)合并就可以更好地利用GPU。

繼而concat層可以消除掉,直接連接到下一層的next input(如下圖)。

另外還可以做并發(fā)(Concurrency),如下圖左半部分(max pool和1×1 CBR)與右半部分(大的1×1 CBR,3×3 CBR和5×5 CBR)彼此之間是相互獨(dú)立的兩條路徑,本質(zhì)上是不相關(guān)的,可以在GPU上通過(guò)并發(fā)來(lái)做,來(lái)達(dá)到的優(yōu)化的目標(biāo)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容