CNN推理優化系列之二:INT8 Quantization
介紹
Low bits壓縮再用於CNN推理當屬該下的推理優化技術主流。
將本是Float32型別的乘法或乘加計算使用INT8型別來做可一次批量(SIMD指令集)執行更多的計算,從而有效提升CNN推理的計算效能。它也是當下CPU能夠在效能與成本上戰勝GPU並牢牢佔據
深度學習模型推理市場90%以上份額的主要原因所在。
最近Facebook推出並開源了fbgemm,它即主要使用INT8計算來代替本來Float32做的事情,在犧牲小部分模型精度的情況下(做得好可控制在1%以內,亦取決於使用者自身對效能與速率之間的取捨),可
達到相對於FP32模型近1~2x的提升。模型權重所佔size也是大大降低。
推本溯源,fbgemm裡所用的low-bits壓縮技術本質上與18年年初Google tensorflow-tflite所用的方法並無二致。而這一方法則在此篇blog要講的paper中曾一一揭示。
典型的Quantization技術
Quantization技術用於深度學習模型推理優化早已有之,並非此paper先創。
但早先的Quantization技術用於推理多是在取得fp32計算訓練好的模型引數權重之後,再對權重進行quantization,然後即使用scale過後的int8(or uint8)權重與op輸入feature maps(亦經scale後變
為了low-bits的表示)進行原本由fp32型別進行的乘法或乘加計算,如此執行所用的ops以完成整個模型推理過程。
而這一inference過程本質上與fp32 train時進行的forward的計算有較大區別的,畢竟在使用fp32型別進行forward/backward計算是並無引入任何scale之類的東西。這樣train出來的weights經由quantized
inference顯然會有較大的精度損失風險。為了避免較大精度損失,成功地在fp32 train時考慮進入scaling的影響,作者們設計了一種與quantization inference相輔相成的帶有simulated quantization的
訓練機制。在我看來它顯然是本篇與之前的quantization方法有最大不同的地方。
下圖a為正式部署時的INT8 quantization計算示例;而圖b則為使用引入了simulation quantization的op訓練時的計算機制;圖c則為與fp32相比,此方法在近乎同等精度下所或得的模型效能提升。

Quantization_inference及帶有Simulation_quantization的training機制
下面我們將分別講述用於部署時的Quantized inference計算過程及方法和引入了simulated quantization的training的計算機制。
Quantized Inference
數學上的等價low-bits表示
經典CNN中,無論GEMM的矩陣乘法運算還是Convolution的乘加計算都是使用fp32進行的。如若我們要使用INT8型別來幾乎無損地模型此以過程(只是INT8與FP32位數表示上的損失我們肯接受,其它則試圖避免),
那麼首先就要在數學上力圖走通。
如下為數學上使用low-bits(int8)來代替FP32的計算過程。
首先,我們想在分別使用low-bits(int8)與FP32表示的模型權重及feature map特徵之間建立一個簡單的單對單對映,如下公式一所示。

INT8與FP32之間的對映
其中r表示fp32表示;q則是low-bit(如int8)表示;S則是自low-bit(int8)到fp32的scale變換,它是個常數,跟具體所變換的tensor相關;Z為零點shift,用於使q的某數值對應於r中的0.0。
由上面公式我們可知,每個fp32型別的tensor可由如下的一個low-bit型別的quantization tensor所表示。

Quantized_tensor表示
int型別的矩陣乘法計算
下面,我們將看下如何使用int型別來等價表示本由fp32型別完成的矩陣乘法計算。準備好了,大波公式來襲!!!

INT型別等價表示的fp32矩陣乘法計算
上述公式2,3,4,5的推理一目瞭然,我們有了上小節中公式1中表示過的fp32與int型別之間的對映關係後,這些都是順理成章的事。有個初中數學的基本就差不多明白如何自公式2至公式4,5的了。
在最終的公式4計算中,可以看出除了與M的乘法計算需要使用浮點數計算外,其它已經都可以使用int型別計算來搞定了。那麼如何將它也搞成更高效率的int計算呢?於是大招來了,下面的近似變換
還是有點trick的,想搞懂的話可能還是要多讀上幾遍。
首先來自Googlers們的強大經驗(我們自己大致亦可感覺出),M一般會是個介於0-1的浮點小數。於是自然是就可將它表示為如下公式6的形式。

天才的公式6
公式6是如何來的呢?如果讀者諸君曾在課程中做過十進位制與二進位制之間表示變換的練習題的話,顯然會更容易理解它。如若沒有做過,呃,那麼好好思索一番吧,你會有頓悟的那一刻的:)。
在公式6中,2 -n 這一部分計算可簡單用int型別的右移指令來搞定。那麼其值在0.5-1之間的M 0 怎麼辦呢?
我們可以使用一個32位的INT型別來表示此一值在0.5-1之間的M 0 。試想將M 0 乘以2 32 則是一個至少為2 31 的整數,如此它就至少可擁有31位的表示精度,因此使用一個INT32型別來表示M 0 還是
很能保證精度的。(當然理解此一近似同樣要求讀者對型別表示等基礎計算機知識有些瞭解。。)
int型別矩陣乘法中零點的高效表示
由上節中的討論,我們已經可以完全使用INT型別計算來完成矩陣乘法了,它在上節中的最終形式為公式4。
而在矩陣乘法中如果一直按照公式4那樣,我們要完成2N 3 減法,同時要使用INT16來表示每對INT8的乘積。
而如果對它進行如下一系列合理、等價的數學變形,我們可得到公式7,並發現其中真正computing intensive的即是公式9表示的INT8乘法計算。

高效的等價變換
典型Fusion layer的計算實現
一般Conv或GEMM計算後我們會有bias加或ReLu等activation函式計算。
在經典的fp32前向推理優化中,我們都會考慮將這些memory-intensive的計算與前面compute-intensive的計算fusion起來一塊進行,以減少對memory-bandwidth的需求。
在int型別計算中顯然也要考慮進去此種fusion layer的影響。
首先,對於bias加,我們可以使用如下的公式10與公式11即使用INT32表示int8乘積之後的加和,然後同時使用INT32來表示bias。在與float32 bias計算對映時,它使用的sclae為
weights tensor scale (S 1 ) 與input feature map tensor scale(S 2 )之間的乘積。

公式10

公式11
對於像ReLu這樣的Activation,我們可考慮直接在INT輸出的feature map上針對某一INT threshold值進行。在此不細表,不是很難,詳情可見論文。
引入了simulated quantization的training
在training的時候引入了scale的機制,即將原來fp32表示的權重與feature map同樣scale到與INT同樣的range裡面(進行一種近似的前向forward計算)。
如下為training時前向計算的scaling機制。

training時前向計算的scaling過程
其它本質上在Quantization inference時,我們也是如此獲得S與Z的,只是在這裡一切皆是用FP32來表示。
即拿到一tensor(weight可feature map),先將其引數限定在某一固有範圍內(a,b),即quantization range,對weights而言,a為min(W),b為max(w),對input而言,因為
變動範圍較大,所以使用一種smooth average 的機制來計算相應的a與b;然後使用quantization level來對其進行scale factor計算。
一般在INT中我們使用INT8的話quantization level就是256。
在最終的q計算中貌似是沒幹啥,其實我們在浮點運算中,這樣除了一下,進行了data rounding to integer,然後再乘回去一切其它已經不同了,那樣特別小的位數顯然已經被清了零。
ok,到了可以進一步總結的時候了。下面的演算法過程基本理清了此一quantization機制的整體操作步驟。

Quantization_Inference與training的計算過程
熟悉tensorflow API的可以看下如下用於構建traing graph及inference graph的過程表示。

tensorflow_code用於構建graph的過程
本來還有點BN fusion的東西,可以一說,可老婆在喊餓唉,所以只能結束掉先閃人了。。讀者君有興趣自己去翻吧,如果真有興趣要使用此技術的話,畢竟都讀到這了。
實驗結果

Quantization在Resnet上的應用

Quantization在Inception v3上的效果
參考文獻
- Quantization and Training of Neural Networks for Efficient Integer-Arithmetic-Only Inference, Benoit-Jacob, 2017
- ofollow,noindex">https://code.fb.com/ml-applications/fbgemm/