日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

TensorRT(5)-INT8校准原理

發(fā)布時(shí)間:2024/9/27 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 TensorRT(5)-INT8校准原理 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

本次講一下 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)范圍:

動(dòng)態(tài)范圍最小正數(shù)
FP32?3.4×1038?+3.4×1038?3.4×1038?+3.4×10381.4×10?451.4×10?45
FP16?65504?+65504?65504?+655045.96×10?85.96×10?8
INT8?128?+127?128?+12711

實(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推理,精度幾乎持平,速度有很大提升。

參考

  • Why are Eight Bits Enough for Deep Neural Networks?
  • Low Precision Inference with TensorRT
  • GTC 2017 Presentation: 8-Bit Inference with TensorRT PPT和演講視頻
  • 維基百科中文版:相對(duì)熵
  • Kullback-Leibler Divergence Explained
  • 引用4的中文版:如何理解K-L散度(相對(duì)熵)
  • 知乎:信息熵是什么?
  • 相對(duì)熵(KL散度)
  • 知乎:如何通俗的解釋交叉熵與相對(duì)熵?
  • 如何理解用信息熵來(lái)表示最短的平均編碼長(zhǎng)度
  • TensorRT Developer Guide
  • 總結(jié)

    以上是生活随笔為你收集整理的TensorRT(5)-INT8校准原理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。