TensorRT(5)-INT8校准原理
本次講一下 tensorRT 的 INT8 低精度推理模式。主要參考?GTC 2017,Szymon Migacz 的PPT?。
1 Low Precision Inference
現(xiàn)有的深度學(xué)習(xí)框架 比如:TensorFlow,Caffe, MixNet等,在訓(xùn)練一個(gè)深度神經(jīng)網(wǎng)絡(luò)時(shí),往往都會(huì)使用 float 32(Full Precise ,簡(jiǎn)稱FP32)的數(shù)據(jù)精度來(lái)表示,權(quán)值、偏置、激活值等。但是如果一個(gè)網(wǎng)絡(luò)很深的話,比如像VGG,ResNet這種,網(wǎng)絡(luò)參數(shù)是極其多的,計(jì)算量就更多了(比如VGG 19.6 billion FLOPS, ResNet-152 11.3 billion FLOPS)。如此多的計(jì)算量,如果中間值都使用 FP 32的精度來(lái)計(jì)算的話,勢(shì)必會(huì)很費(fèi)時(shí)間。而這對(duì)于嵌入式設(shè)備或者移動(dòng)設(shè)備來(lái)說(shuō),簡(jiǎn)直就是噩夢(mèng),因?yàn)樗麄兊挠?jì)算能力和內(nèi)存數(shù)量是不能與PC相比的。
因此解決此問(wèn)題的方法之一就是在部署推理時(shí)(inference)使用低精度數(shù)據(jù),比如INT8。除此之外,當(dāng)然還有模型壓縮之類的方法,不過(guò)此處不做探究。注意此處只是針對(duì) 推理階段,訓(xùn)練時(shí)仍然使用 FP32的精度。
從經(jīng)驗(yàn)上來(lái)分析一下低精度推理的可行性:
實(shí)際上有些人認(rèn)為,即便在推理時(shí)使用低精度的數(shù)據(jù)(比如INT8),在提升速度的同時(shí),也并不會(huì)造成太大的精度損失,比如?Why are Eight Bits Enough for Deep Neural Networks??以及Low Precision Inference with TensorRT?這兩篇博文。
文章的作者認(rèn)為網(wǎng)絡(luò)在訓(xùn)練的過(guò)程中學(xué)習(xí)到了數(shù)據(jù)樣本的模式可分性,同時(shí)由于數(shù)據(jù)中存在的噪聲,使得網(wǎng)絡(luò)具有較強(qiáng)的魯棒性,也就是說(shuō)在輸入樣本中做輕微的變動(dòng)并不會(huì)過(guò)多的影響結(jié)果性能。與圖像上目標(biāo)間的位置,姿態(tài),角度等的變化程度相比,這些噪聲引進(jìn)的變動(dòng)只是很少的一部分,但實(shí)際上這些噪聲引進(jìn)的變動(dòng)同樣會(huì)使各個(gè)層的激活值輸出發(fā)生變動(dòng),然而卻對(duì)結(jié)果影響不大,也就是說(shuō)訓(xùn)練好的網(wǎng)絡(luò)對(duì)這些噪聲具有一定的容忍度(tolerance )。
正是由于在訓(xùn)練過(guò)程中使用高精度(FP32)的數(shù)值表示,才使得網(wǎng)絡(luò)具有一定的容忍度。訓(xùn)練時(shí)使用高精度的數(shù)值表示,可以使得網(wǎng)絡(luò)以很小的計(jì)算量修正參數(shù),這在網(wǎng)絡(luò)最后收斂的時(shí)候是很重要的,因?yàn)槭諗康臅r(shí)候要求修正量很小很小(一般訓(xùn)練初始 階段學(xué)習(xí)率稍大,越往后學(xué)習(xí)率越小)。
那么如果使用低精度的數(shù)據(jù)來(lái)表示網(wǎng)絡(luò)參數(shù)以及中間值的話,勢(shì)必會(huì)存在誤差,這個(gè)誤差某種程度上可以認(rèn)為是一種噪聲。那也就是說(shuō),使用低精度數(shù)據(jù)引進(jìn)的差異是在網(wǎng)絡(luò)的容忍度之內(nèi)的,所以對(duì)結(jié)果不會(huì)產(chǎn)生太大影響。
以上分析都是基于經(jīng)驗(yàn)的,理論上的分析比較少,不過(guò)文章提到了兩篇 paper,如下:
- Improving the speed of neural networks on CPUs
- Training deep neural networks with low precision multiplications
這里不對(duì)這兩篇paper做探究。
TensorRT 的INT8模式只支持計(jì)算能力為6.1的GPU(Compute Capability 6.1 ),比如: GP102 (Tesla P40 and NVIDIA Titan X), GP104 (Tesla P4), and GP106 GPUs,主要根源是這些GPU支持 DP4A硬件指令。DP4A下面會(huì)稍微介紹一下。
2 TensorRT INT8 Inference
首先看一下不同精度的動(dòng)態(tài)范圍:
| FP32 | ?3.4×1038?+3.4×1038?3.4×1038?+3.4×1038 | 1.4×10?451.4×10?45 |
| FP16 | ?65504?+65504?65504?+65504 | 5.96×10?85.96×10?8 |
| INT8 | ?128?+127?128?+127 | 11 |
實(shí)際上將FP32的精度降為INT8還是比較具有挑戰(zhàn)性的。
2.1 Quantization
將FP32降為INT8的過(guò)程相當(dāng)于信息再編碼(re-encoding information ),就是原來(lái)使用32bit來(lái)表示一個(gè)tensor,現(xiàn)在使用8bit來(lái)表示一個(gè)tensor,還要求精度不能下降太多。
將FP32轉(zhuǎn)換為 INT8的操作需要針對(duì)每一層的輸入張量(tensor)和 網(wǎng)絡(luò)學(xué)習(xí)到的參數(shù)(learned parameters)進(jìn)行。
首先能想到的最簡(jiǎn)單的映射方式就是線性映射(或稱線性量化,linear quantization), 就是說(shuō)映射前后的關(guān)系滿足下式:
FP32 Tensor (T) = scale_factor(sf) * 8-bit Tensor(t) + FP32_bias (b)FP32 Tensor (T) = scale_factor(sf) * 8-bit Tensor(t) + FP32_bias (b)
試驗(yàn)證明,偏置實(shí)際上是不需要的,因此去掉偏置,也就是
T=sf?tT=sf?t
sfsf?是每一層上每一個(gè)tensor的換算系數(shù)或稱比例因子(scaling factor),因此現(xiàn)在的問(wèn)題就變成了如何確定比例因子。然后最簡(jiǎn)單的方法是下圖這樣的:
- 簡(jiǎn)單的將一個(gè)tensor 中的 -|max| 和 |max| FP32 value 映射為 -127 和 127 ,中間值按照線性關(guān)系進(jìn)行映射。
- 稱這種映射關(guān)系為不飽和的(No saturation ),對(duì)稱的。
但是試驗(yàn)結(jié)果顯示這樣做會(huì)導(dǎo)致比較大的精度損失。
下面這張圖展示的是不同網(wǎng)絡(luò)結(jié)構(gòu)的不同layer的激活值分布,有卷積層,有池化層,他們之間的分布很不一樣,因此合理的 量化方式 應(yīng)該適用于不同的激活值分布,并且減小 信息損失。因?yàn)閺腇P32到INT8其實(shí)就是一種信息再編碼的過(guò)程。
正在上傳…重新上傳取消
?
我個(gè)人理解的直接使用線性量化的方式導(dǎo)致精度損失比較大的原因是:
- 上圖是一些網(wǎng)絡(luò)模型中間層的 激活值統(tǒng)計(jì),橫坐標(biāo)是激活值,縱坐標(biāo)是統(tǒng)計(jì)數(shù)量的歸一化表示,這里是歸一化表示,不是絕對(duì)數(shù)值統(tǒng)計(jì);
- 這個(gè)激活值統(tǒng)計(jì) 針對(duì)的是一批圖片,不同的圖片輸出的激活值不完全相同。所以圖上并不是一條曲線而是多條曲線(一張圖片對(duì)應(yīng)一條曲線,或者稱為散點(diǎn)圖更好一點(diǎn)),只不過(guò)前面一部分重復(fù)在一塊了(紅色虛線圈起來(lái)的部分),說(shuō)明對(duì)于不同圖片生成的大部分激活值其分布是相似的;但是在激活值比較大時(shí)(紅色實(shí)線圈起來(lái)的部分),曲線不重復(fù)了,一個(gè)激活值對(duì)應(yīng)多個(gè)不同的統(tǒng)計(jì)量,這時(shí)的激活值分布就比較亂了。
- 后面這一部分在整個(gè)層中是占少數(shù)的(占比很小,比如10^-9, 10^-7, 10^-3),因此后面這一段完全可以不考慮到映射關(guān)系中去,保留激活值分布的主方向。開(kāi)始我以為網(wǎng)絡(luò)之所以能把不同類別的圖片分開(kāi)是由于后面實(shí)線部分的差異導(dǎo)致的,后來(lái)想了一下:這個(gè)并不包含空間位置的分布,只是數(shù)值上的分布,所以后面的應(yīng)該對(duì)結(jié)果影響不大。
因此TensorRT的做法是:
正在上傳…重新上傳取消
- 這種做法不是將 ±|max| 映射為 ±127,而是存在一個(gè) 閾值 |T| ,將 ±|T| 映射為±127,顯然這里 |T|<|max|。
- 超出 閾值 ±|T| 外的直接映射為閾值 ±127。比如上圖中的三個(gè)紅色點(diǎn),直接映射為-127。
- 稱這種映射關(guān)系為飽和的(Saturate ),不對(duì)稱的。
- 只要 閾值 選取得當(dāng),就能將分布散亂的較大的激活值舍棄掉,也就有可能使精度損失不至于降低太多。
網(wǎng)絡(luò)的前向計(jì)算涉及到兩部分?jǐn)?shù)值:權(quán)值和激活值(weights 和activation,二者要做乘法運(yùn)算),Szymon Migacz 也提到他們?cè)?jīng)做過(guò)實(shí)驗(yàn),說(shuō)對(duì)weights 做saturation 沒(méi)有什么變化,因此 對(duì)于weights的int8量化就使用的是不飽和的方式;而對(duì)activation做saturation就有比較顯著的性能提升,因此對(duì)activation使用的是飽和的量化方式。
那現(xiàn)在的問(wèn)題是 如何確定|T|?我們來(lái)思考一下,現(xiàn)在有一個(gè)FP32的tensor,FP32肯定是能夠表達(dá)這個(gè)tensor的最佳分布。現(xiàn)在我們要用一個(gè)不同的分布(INT8)來(lái)表達(dá)這個(gè)tensor,這個(gè) INT8 分布不是一個(gè)最佳的分布。飽和的INT8分布由于閾值 |T|的取值會(huì)有很多種情況(128?|max|128?|max|),其中肯定有一種情況是相對(duì)其他最接近FP32的,我們就是要把這種情況找出來(lái)。
既然如此,我們就需要一個(gè)衡量指標(biāo)來(lái)衡量不同的 INT8 分布與原來(lái)的FP3F2分布之間的差異程度。這個(gè)衡量指標(biāo)就是?相對(duì)熵(relative entropy),又稱為KL散度(Kullback–Leibler divergence,簡(jiǎn)稱KLD),信息散度(information divergence),信息增益(information gain)。叫法實(shí)在太多了,最常見(jiàn)的就是相對(duì)熵。跟交叉熵也是有關(guān)系的。
-
假設(shè)我們要給一個(gè)信息進(jìn)行完美編碼,那么最短平均編碼長(zhǎng)度就是信息熵。
-
如果編碼方案不一定完美(由于對(duì)概率分布的估計(jì)不一定正確),這時(shí)的平均編碼長(zhǎng)度就是交叉熵。
平均編碼長(zhǎng)度 = 最短平均編碼長(zhǎng)度 + 一個(gè)增量
交叉熵在深度學(xué)習(xí)中廣泛使用,衡量了測(cè)試集標(biāo)簽分布和模型預(yù)測(cè)分布之間的差異程度。
-
編碼方法不一定完美時(shí),平均編碼長(zhǎng)度相對(duì)于最小值的增加量(即上面那個(gè)增量)是相對(duì)熵。
即?交叉熵=信息熵+相對(duì)熵
通俗的理解 信息熵,交叉熵,相對(duì)熵,參考:知乎:如何通俗的解釋交叉熵與相對(duì)熵?
如何理解信息熵用來(lái)表示最短平均編碼長(zhǎng)度,參考:?如何理解用信息熵來(lái)表示最短的平均編碼長(zhǎng)度
詳細(xì)的不說(shuō)了,請(qǐng)看參考鏈接。
在這里,FP32的tensor就是我們要表達(dá)的信息量,FP32也是最佳分布(可以認(rèn)為最短編碼長(zhǎng)度32bit),現(xiàn)在要做的是使用INT8 來(lái)編碼FP32的信息,同時(shí)要求INT8編碼后差異盡可能最小。考慮兩個(gè)分布 P(FP32)、Q(INT8)KL散度計(jì)算如下:
KL_divergence(P,Q):= SUM(P[i] * log(P[i] / Q[i] ), i)KL_divergence(P,Q):= SUM(P[i] * log(P[i] / Q[i] ), i)
P,Q分別稱為 reference_distribution、 quantize _distribution
實(shí)際上這里也說(shuō)明了每一層的tensor 的 |T| 值都是不一樣的。
確定每一層的 |T|值的過(guò)程稱為 校準(zhǔn)(Calibration )。
2.2 Calibration
上面已經(jīng)說(shuō)了 KL散度越小代表 INT8編碼后的信息損失越少。這一節(jié)來(lái)看看如何根據(jù)KL散度尋找最佳INT8分布。其實(shí)前面我們也已經(jīng)提到了,如果要讓最后的精度損失不大,是要考慮一些先驗(yàn)知識(shí)的,這個(gè)先驗(yàn)知識(shí)就是每一層在 FP32精度下的激活值分布,只有根據(jù)這個(gè)才能找到更加合理的 閾值|T|。也就是說(shuō)首先得有一個(gè)以FP32精度訓(xùn)練好的模型。基本上現(xiàn)有的深度學(xué)習(xí)框架都是默認(rèn) FP32精度的,有些模型還支持FP16精度訓(xùn)練,貌似 Caffe2和MXNet是支持FP16的,其他的不太清楚。所以基本上只要沒(méi)有特別設(shè)定,訓(xùn)練出來(lái)的模型肯定是 FP32 的。
那激活值分布如何得到?難道我們要將FP32的模型先在所有的測(cè)試集(或驗(yàn)證集)上跑一邊記錄下每一層的FP32激活值,然后再去推斷 |T|?
這里的做法是 從驗(yàn)證集 選取一個(gè)子集作為校準(zhǔn)集(Calibration Dataset ),校準(zhǔn)集應(yīng)該具有代表性,多樣性,最好是驗(yàn)證集的一個(gè)子集,不應(yīng)該只是分類類別的一小部分。激活值分布就是從校準(zhǔn)集中得到的。
按照NVIDIA 官方的說(shuō)法:
Note: The calibration set must be representative of the input provided to TensorRT at runtime; for example, for image classification networks, it should not consist of images from just a small subset of categories. For ImageNet networks, around 500 calibration images is adequate.
對(duì)于ImageNet 數(shù)據(jù)集來(lái)說(shuō) 校準(zhǔn)集大小一般500張圖片就夠了(Szymon Migacz的演講說(shuō)用1000張),這里有點(diǎn)懷疑也有點(diǎn)震驚,沒(méi)想到 ImageNet 1000個(gè)分類,100多萬(wàn)張圖片,500張就夠了,不過(guò)從2.5節(jié)的圖表中的結(jié)果可以看出500張確實(shí)夠了。
然后要做的是:
- 首先在 校準(zhǔn)集上 進(jìn)行 FP32 inference 推理;
- 對(duì)于網(wǎng)絡(luò)的每一層(遍歷):
- 收集這一層的激活值,并做 直方圖(histograms ),分成幾個(gè)組別(bins)(官方給的一個(gè)說(shuō)明使用的是2048組),分組是為了下面遍歷 |T| 時(shí),減少遍歷次數(shù);
- 對(duì)于不同的 閾值 |T| 進(jìn)行遍歷,因?yàn)檫@里 |T|的取值肯定在 第128-2047 組之間,所以就選取每組的中間值進(jìn)行遍歷;
- 選取使得 KL_divergence(ref_distr, quant_distr) 取得最小值的 |T|。
- 返回一系列 |T|值,每一層都有一個(gè) |T|。創(chuàng)建?CalibrationTable?。
上面解釋一下:假設(shè) 最后 使得 KL散度最小的|T|值是第200組的中間值,那么就把原來(lái) 第 0-200組的 數(shù)值線性映射到 0-128之間,超出范圍的直接映射到128。
正在上傳…重新上傳取消
?
校準(zhǔn)的過(guò)程可以參考一下這個(gè):https://www.jianshu.com/p/43318a3dc715,?這篇文章提供了一個(gè)詳細(xì)的根據(jù)KL散度來(lái)將原始信息進(jìn)行編碼的例子,包括直方圖的使用。跟這里的校準(zhǔn)過(guò)程極為相像。
下面是一個(gè)官方?GTC2017 PPT?中給的校準(zhǔn)的偽代碼:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
//首先分成 2048個(gè)組,每組包含多個(gè)數(shù)值(基本都是小數(shù)) Input: FP32 histogram H with 2048 bins: bin[ 0 ], …, bin[ 2047 ] For i in range( 128 , 2048 ): // |T|的取值肯定在 第128-2047 組之間,取每組的中點(diǎn) reference_distribution_P = [ bin[ 0 ] , ..., bin[ i-1 ] ] // 選取前 i 組構(gòu)成P,i>=128 outliers_count = sum( bin[ i ] , bin[ i+1 ] , … , bin[ 2047 ] ) //邊界外的組 reference_distribution_P[ i-1 ] += outliers_count //邊界外的組加到邊界P[i-1]上,沒(méi)有直接丟掉 P /= sum(P) // 歸一化 // 將前面的P(包含i個(gè)組,i>=128),映射到 0-128 上,映射后的稱為Q,Q包含128個(gè)組, // 一個(gè)整數(shù)是一組 candidate_distribution_Q = quantize [ bin[ 0 ], …, bin[ i-1 ] ] into 128 levels //這時(shí)的P(包含i個(gè)組,i>=128)和Q向量(包含128個(gè)組)的大小是不一樣的,無(wú)法直接計(jì)算二者的KL散度 //因此需要將Q擴(kuò)展為 i 個(gè)組,以保證跟P大小一樣 expand candidate_distribution_Q to ‘ i ’ bins Q /= sum(Q) // 歸一化 //計(jì)算P和Q的KL散度 divergence[ i ] = KL_divergence( reference_distribution_P, candidate_distribution_Q) End For //找出 divergence[ i ] 最小的數(shù)值,假設(shè) divergence[m] 最小, //那么|T|=( m + 0.5 ) * ( width of a bin ) Find index ‘m’ for which divergence[ m ] is minimal threshold = ( m + 0.5 ) * ( width of a bin ) |
解釋一下第16行:
- 計(jì)算KL散度 KL_divergence(P, Q) 時(shí),要求序列P和Q的長(zhǎng)度一致,即 len(P) == len(Q);
- Candidate_distribution_Q 是將 P 線性映射到 128個(gè)bins得到的,長(zhǎng)度為128。而reference_distribution_P 包含 i (i>=128)個(gè) bins (bin[0] - bin[i-1] ),二者長(zhǎng)度不等;
- 需要將 candidate_distribution_Q 擴(kuò)展回 i 個(gè)bins 然后才能與 i個(gè)bins 的 reference_distribution_P計(jì)算KL散度。
舉個(gè)簡(jiǎn)單的栗子:
-
假設(shè)reference_distribution_P 包含 8 個(gè)bins(這里一個(gè)bin就只包含一個(gè)數(shù)據(jù)):
P = [ 1, 0, 2, 3, 5, 3, 1, 7]
-
我們想把它映射為 2 個(gè)bins,于是 4個(gè)一組合并:
[1 + 0 + 2 + 3 , 5 + 3 + 1 + 7] = [6, 16]
-
然后要成比例的 擴(kuò)展回到 8個(gè)組,保留原來(lái)是0的組:
Q = [ 6/3, 0, 6/3, 6/3, 16/4, 16/4, 16/4, 16/4] = [ 2, 0, 2, 2, 4, 4, 4, 4]
-
然后對(duì) P和Q進(jìn)行標(biāo)準(zhǔn)化:
P /= sum(P) 、Q /= sum(Q)
-
最后計(jì)算散度:
result = KL_divergence(P, Q)
我們來(lái)看看 ResNet-152中 res4b30層校準(zhǔn)前后的結(jié)果對(duì)比:
?
- 圖中那個(gè)白線就是 |T|的取值,不過(guò)怎么還小于128了,有點(diǎn)沒(méi)搞明白。
再看看其他幾種網(wǎng)絡(luò)的校準(zhǔn)情況:
2.3 DP4A(Dot?Product of?4?8-bits?Accumulated to a 32-bit)
TensorRT 進(jìn)行優(yōu)化的方式是 DP4A (Dot?Product of?4?8-bits?Accumulated to a 32-bit),如下圖:
這是PASCAL 系列GPU的硬件指令,INT8卷積就是使用這種方式進(jìn)行的卷積計(jì)算。
這個(gè)沒(méi)搞太明白是怎么回事,參考這篇博客獲取詳細(xì)信息Mixed-Precision Programming with CUDA 8
下面是 官方?GTC2017 PPT?中給的INT8卷積計(jì)算的偽代碼:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
// I8 input tensors: I8_input, I8_weights, INT8輸入tensor // I8 output tensors: I8_output, INT8輸出tensor // F32 bias (original bias from the F32 model),FP32的偏置 // F32 scaling factors: input_scale, output_scale, weights_scale[K], 這個(gè)是前面說(shuō)的縮放因子sf I32_gemm_out = I8_input * I8_weights // Compute INT8 GEMM (DP4A),卷積計(jì)算,INT32輸出 F32_gemm_out = (float)I32_gemm_out // Cast I32 GEMM output to F32 float,強(qiáng)制轉(zhuǎn)換為FP32 //前面計(jì)算I8_input * I8_weights時(shí),總的縮放系數(shù)為 input_scale * weights_scale[K] //但是輸出的縮放系數(shù)為output_scale,所以為了保證縮放程度匹配,要將F32_gemm_out乘以 //output_scale / (input_scale * weights_scale[ i ] ) // At this point we have F32_gemm_out which is scaled by ( input_scale * weights_scale[K] ), // but to store the final result in int8 we need to have scale equal to "output_scale", so we have to rescale: // (this multiplication is done in F32, *_gemm_out arrays are in NCHW format) For i in 0, ... K-1: rescaled_F32_gemm_out[ :, i, :, :] = F32_gemm_out[ :, i, :, :] * [ output_scale /(input_scale * weights_scale[ i ] ) ] //將FP32精度的偏置 乘上縮放因子,加到前面的計(jì)算結(jié)果中 // Add bias, to perform addition we have to rescale original F32 bias so that it's scaled with "output_scale" rescaled_F32_gemm_out _with_bias = rescaled_F32_gemm_out + output_scale * bias //ReLU 激活 // Perform ReLU (in F32) F32_result = ReLU(rescaled_F32_gemm_out _with_bias) //重新轉(zhuǎn)換為 INT8 // Convert to INT8 and save to global I8_output = Saturate( Round_to_nearest_integer( F32_result ) ) |
它這個(gè)INT8卷積的計(jì)算是這樣的,雖然輸入的tensor已經(jīng)降為 INT8,但是在卷積計(jì)算的時(shí)候用了DP4A的計(jì)算模式,卷積計(jì)算完之后是INT32的,然后又要轉(zhuǎn)成 FP32,然后激活,最后再將FP32的轉(zhuǎn)為INT8.
只知道這么計(jì)算會(huì)快很多,但不知道為什么,詳情還是看Mixed-Precision Programming with CUDA 8?這個(gè)吧,我看的也是糊里糊涂的。
不過(guò)這個(gè)對(duì)于tensorRT的使用沒(méi)啥影響,這個(gè)是很底層的東西,涉及到硬件優(yōu)化。
2.4 Typical workflow in TensorRT
典型的工作流還是直接使用?GTC2017 PPT?原文說(shuō)法吧:
- You will need:
- Model trained in FP32.
- Calibration dataset.
- TensorRT will:
- Run inference in FP32 on calibration dataset.
- Collect required statistics.
- Run calibration algorithm → optimal scaling factors.
- Quantize FP32 weights → INT8.
- Generate “CalibrationTable” and INT8 execution engine.
2.5 Results - Accuracy & Performance
精度并沒(méi)有損失太多
速度提升還蠻多的,尤其是當(dāng) batch_size 大于1時(shí),提升更明顯
TITAN X GPU優(yōu)化效果
DRIVE PX 2, dGPU 優(yōu)化效果
2.6 Open challenges / improvements
一些開(kāi)放式的提升和挑戰(zhàn):
- Unsigned int8 for activations after ReLU. 無(wú)符號(hào) INT8 的映射。
- RNNs → open research problem. TensorRT 3.0開(kāi)始已經(jīng)支持RNN了。
- Fine tuning of saturation thresholds. 對(duì)閾值 |T|的 微調(diào)方法。
- Expose API for accepting custom, user provided scale factors. 開(kāi)放API,使用戶可以自定義 換算系數(shù)(比例因子)
這幾個(gè)開(kāi)放問(wèn)題還是很值得研究的。
3 Conclusion
- 介紹了一種自動(dòng)化,無(wú)參數(shù)的 FP32 到 INT8 的轉(zhuǎn)換方法;
- 對(duì)稱的,不飽和的線性量化,會(huì)導(dǎo)致精度損失較大;
- 通過(guò)最小化 KL散度來(lái)選擇 飽和量化中的 閾值 |T|;
- FP32完全可以降低為INT8推理,精度幾乎持平,速度有很大提升。
參考
總結(jié)
以上是生活随笔為你收集整理的TensorRT(5)-INT8校准原理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: TensorRT(4)-Profilin
- 下一篇: TensorRT(6)-INT8 inf