戰(zhàn):FP32到INT8部署提速指南)
上一期線上項(xiàng)目里我接手了一個(gè)推理慢到?jīng)]法用的模型訓(xùn)練精度明明很漂亮一到部署環(huán)境就卡在延遲預(yù)算外面。團(tuán)隊(duì)里有人提議換更輕量的骨干網(wǎng)絡(luò)有人建議上剪枝我最后選了先試模型量化從FP32壓到INT8花了一個(gè)多星期把精度與速度的平衡點(diǎn)調(diào)好整體推理提速接近翻倍模型體積直接縮到四分之一。這篇就把我從原理到落地的完整過程寫清楚包括怎么算量化參數(shù)、怎么準(zhǔn)備校準(zhǔn)數(shù)據(jù)、精度掉點(diǎn)之后如何一步步排查以及哪些場景其實(shí)不適合硬上INT8。不管你是剛開始接觸部署的新人還是已經(jīng)在邊緣設(shè)備上折騰過幾輪的從業(yè)者這篇里的流程和坑都能直接用。1. 部署場景的FP32困局內(nèi)存與算力先算賬很多人一聽到量化第一反應(yīng)是會(huì)掉精度吧然后就不愿意碰。但部署場景里FP32的問題從來都是硬性的模型太大、推理太慢、功耗太高。做決定之前先把賬算明白。1.1 模型體積四倍差距在存儲(chǔ)受限時(shí)是硬門檻假設(shè)你手里有一個(gè)一億參數(shù)的模型FP32每個(gè)參數(shù)占4字節(jié)模型文件就是400MB左右。如果目標(biāo)設(shè)備可用內(nèi)存只有1GB光加載權(quán)重就占掉近一半再加上輸入輸出緩沖、運(yùn)行時(shí)中間特征圖、推理引擎自身的開銷頻繁出現(xiàn)內(nèi)存不足幾乎是必然的。換成INT8之后同樣的參數(shù)每個(gè)只占1字節(jié)模型體積直接降到100MB。省下來的300MB能留給推理引擎做顯存或內(nèi)存管理給批處理留出空間也能讓模型在低配機(jī)器上跑起來。存儲(chǔ)端也一樣。移動(dòng)場景要看包體大小400MB和100MB對(duì)用戶的下載意愿、安裝成功率影響很大。哪怕不考慮速度單憑體積這個(gè)理由量化就值得做。我實(shí)際接觸的那些邊緣盒子和老款開發(fā)板很多FP32模型連裝都裝不進(jìn)去INT8是唯一不需要改網(wǎng)絡(luò)結(jié)構(gòu)就能塞進(jìn)去的方案。1.2 推理延遲INT8的提升從哪來延遲收益主要來自兩個(gè)方向計(jì)算更快搬運(yùn)更快。先看計(jì)算。FP32做一次乘加運(yùn)算數(shù)據(jù)是32位INT8只有8位。支持INT8加速指令的處理器一個(gè)時(shí)鐘周期能處理的運(yùn)算數(shù)往往是FP32的2到4倍。從算術(shù)邏輯上看位寬降了四倍單條向量指令能打包的數(shù)據(jù)也多了四倍吞吐量自然上去。再看搬運(yùn)。現(xiàn)代處理器做推理時(shí)很大一部分時(shí)間不是花在計(jì)算上而是花在把權(quán)重從內(nèi)存搬進(jìn)計(jì)算單元。數(shù)據(jù)位寬降到原來的四分之一同樣的內(nèi)存帶寬下能搬四倍的參數(shù)訪存瓶頸被明顯緩解。對(duì)卷積這類權(quán)重復(fù)用高的算子計(jì)算密集程度高提速主要靠計(jì)算指令對(duì)全連接、Embedding這類訪存密集的算子提速主要靠帶寬收益。我實(shí)測下來常見的卷積分類網(wǎng)絡(luò)在支持INT8加速的CPU上整體延遲通常能到FP32的1.5到3倍收益具體取決于算子組成和硬件指令支持情況。這個(gè)數(shù)值不是到處都適用但作為預(yù)期參考沒問題。1.3 功耗與吞吐服務(wù)端成本里容易被忽略的部分邊緣設(shè)備上功耗是硬約束電池供電的設(shè)備推理功耗降不下來產(chǎn)品就沒法用。INT8計(jì)算單元功耗遠(yuǎn)低于FP32同樣的任務(wù)能耗能省一半以上。服務(wù)端場景電池不敏感但吞吐敏感單卡并發(fā)能翻倍意味著同樣一批服務(wù)器能承載雙倍請(qǐng)求電費(fèi)、散熱、機(jī)柜成本都跟著降。量化不是免費(fèi)的午餐它用精度換取這些收益。但很多時(shí)候精度損失是可控的損失往往只有0.1%到1%之間而收益是實(shí)打?qū)嵉膸妆?。下面就把原理講透讓你知道精度損失到底出在哪怎么控制它。2. 量化原理從浮點(diǎn)數(shù)到整數(shù)的映射邏輯量化本質(zhì)上是一個(gè)數(shù)值映射問題把一個(gè)連續(xù)取值范圍內(nèi)的浮點(diǎn)數(shù)映射到有限個(gè)離散整數(shù)上。想用好它就要理解映射公式和誤差來源。2.1 核心公式與一個(gè)生活化類比最常用的量化映射公式是q round(r / S) Z r ≈ S * (q - Z)其中r是原始浮點(diǎn)值q是量化后的整數(shù)S是縮放系數(shù)scaleZ是零點(diǎn)偏移zero point。反量化時(shí)用第二個(gè)公式還原出近似的浮點(diǎn)值。用一個(gè)類比理解假設(shè)你有一缸水要倒進(jìn)一個(gè)只有256個(gè)刻度的量杯里8位整數(shù)就是從0到255或從-128到127。S就是每個(gè)刻度代表多少水Z就是刻度0對(duì)應(yīng)的水面位置。量杯刻度太粗倒進(jìn)去的水位必然會(huì)和真實(shí)水面有誤差這就是量化誤差。這個(gè)誤差分為兩部分。第一部分是取整誤差數(shù)值落在兩個(gè)刻度之間只能就近選一個(gè)round這一步天然有舍入誤差。第二部分是截?cái)嗾`差數(shù)值超出量程被強(qiáng)行截到邊界這部分誤差往往更大。量化時(shí)最核心的權(quán)衡就在這里量程設(shè)得寬離群點(diǎn)不容易被截?cái)嗟總€(gè)刻度代表的范圍變大取整誤差變大量程設(shè)得窄取整更精細(xì)但離群點(diǎn)會(huì)被狠切一刀。怎么取舍就是校準(zhǔn)方法要解決的事。2.2 對(duì)稱量化與非對(duì)稱量化零點(diǎn)偏移為什么重要對(duì)稱量化直接讓Z等于0整數(shù)范圍取-128到127正負(fù)對(duì)稱。好處是計(jì)算簡單反量化少一次減法壞處是如果數(shù)值分布不在零附近對(duì)稱有一半的量化區(qū)間是浪費(fèi)的。非對(duì)稱量化保留Z整數(shù)范圍通常取0到255。激活值經(jīng)過ReLU之后全是非負(fù)的分布嚴(yán)重偏向正數(shù)這時(shí)用非對(duì)稱量化可以把256個(gè)刻度全部用在有效區(qū)間上量化精度明顯更高。這就是為什么實(shí)際工程里權(quán)重常用對(duì)稱量化激活常用非對(duì)稱量化。零點(diǎn)偏移還有一個(gè)容易被忽略的作用保證浮點(diǎn)0在量化后依然精確對(duì)應(yīng)0。對(duì)于卷積層的padding操作和ReLU前的偏置累加0是一個(gè)特殊且頻繁出現(xiàn)的值如果0被量化出去之后還原不回來會(huì)在卷積計(jì)算中引入系統(tǒng)性偏移誤差逐層累積。保留Z本質(zhì)上就是確保0這個(gè)值不被round誤差破壞。2.3 校準(zhǔn)方法min-max、百分位與熵校準(zhǔn)的區(qū)別確定S和Z需要知道每層激活值的實(shí)際范圍。權(quán)重的范圍可以直接在權(quán)重張量上算但激活的范圍必須靠數(shù)據(jù)跑出來這個(gè)環(huán)節(jié)叫校準(zhǔn)calibration用來跑的數(shù)據(jù)叫校準(zhǔn)數(shù)據(jù)集。最簡單的方法叫min-max跑一遍校準(zhǔn)數(shù)據(jù)記錄每層激活的最小值和最大值直接把S設(shè)為(max-min)/255。實(shí)話說我在多數(shù)圖像分類模型上先用min-max驗(yàn)證往往已經(jīng)能滿足要求。但min-max有一個(gè)致命弱點(diǎn)它對(duì)離群點(diǎn)極其敏感。只要有一兩個(gè)激活值異常大整個(gè)量程就被拉寬大部分正常值擠在幾個(gè)刻度里精度立刻崩。百分位校準(zhǔn)解決的就是這個(gè)問題取99.99%分位數(shù)而不是絕對(duì)最大值主動(dòng)放棄尾部那0.01%的極端值換回大部分正常值更精細(xì)的表示。損失的是離群點(diǎn)的精度但這些點(diǎn)本來就是少數(shù)對(duì)整體分布影響有限。熵校準(zhǔn)的思路更講究一點(diǎn)遍歷候選閾值計(jì)算把分布截?cái)嗟皆撻撝岛蟮牧炕植己驮几↑c(diǎn)分布的KL散度選散度最小的閾值。本質(zhì)上是找信息損失最小的截?cái)辔恢糜眯畔⒄摰囊暯翘娣植颊乙粋€(gè)最劃算的裁切點(diǎn)。它比百分位更貼合數(shù)據(jù)分布但也更慢。實(shí)操中我會(huì)先用min-max快速看掉點(diǎn)幅度掉點(diǎn)超過容忍線再換百分位或熵校準(zhǔn)而不是一上來就上復(fù)雜方法。2.4 按張量還是按通道量化粒度的取舍量化粒度說的是S和Z是整層共用一份還是每個(gè)通道各一份。按張量per-tensor量化整層一個(gè)S一個(gè)Z對(duì)硬件最友好實(shí)現(xiàn)最簡單大部分推理引擎的默認(rèn)方案。問題在于卷積層的權(quán)重分布往往不是均勻的不同輸出通道的數(shù)值范圍可能差出好幾倍。一份S被大范圍通道主導(dǎo)小范圍通道的有效位寬就被壓縮精度損失集中在小范圍通道上。按通道per-channel量化每個(gè)輸出通道單獨(dú)算S和Z權(quán)重量化精度顯著提升。代價(jià)是計(jì)算復(fù)雜度增加部分硬件不支持部署時(shí)要先確認(rèn)硬件能力。我的經(jīng)驗(yàn)是權(quán)重優(yōu)先用per-channel激活保持per-tensor。激活的通道間差異通常沒有權(quán)重那么極端而per-channel激活量化在硬件上實(shí)現(xiàn)成本高、收益有限投入產(chǎn)出比不劃算。分組量化是介于兩者之間的方案把權(quán)重按固定大小分組每組一個(gè)S常用在Transformer場景。NLP模型權(quán)重動(dòng)態(tài)范圍大per-tensor太粗per-channel不夠靈活分組量化就成了折中利器這個(gè)后面再說。3. FP32到INT8的完整落地流程原理清楚之后落地就是一套標(biāo)準(zhǔn)化動(dòng)作。我把流程拆成四步每一步都有需要注意的細(xì)節(jié)。3.1 第一步BN折疊與網(wǎng)絡(luò)的靜態(tài)化動(dòng)手量化之前第一件事是處理BatchNorm層。BN在訓(xùn)練時(shí)做歸一化推理時(shí)變換可以寫成y gamma * (x - mean) / sqrt(var eps) beta。如果輸入x來自卷積層的輸出這整個(gè)變換能折疊進(jìn)卷積的權(quán)重和偏置里推理時(shí)不需要單獨(dú)計(jì)算BN。BN不折疊直接量化的后果很嚴(yán)重。量化時(shí)激活范圍來自卷積輸出但BN會(huì)在線性變換激活的分布量化參數(shù)和實(shí)際分布對(duì)不上精度掉得毫無道理。我在最早一次實(shí)驗(yàn)里跳過這一步整體分類精度從FP32的91%直接掉到82%排查了很久才發(fā)現(xiàn)是BN折疊沒做徹底。實(shí)操上先用推理引擎自帶的算子融合功能檢查BN是否已經(jīng)并進(jìn)卷積。有些框架在導(dǎo)出推理模型時(shí)會(huì)自動(dòng)折疊但模型結(jié)構(gòu)稍復(fù)雜或跳連較多時(shí)容易漏。穩(wěn)妥的做法是寫一個(gè)腳本導(dǎo)出后遍歷網(wǎng)絡(luò)結(jié)構(gòu)確認(rèn)BN層已經(jīng)消失或已經(jīng)變成Identity。3.2 第二步校準(zhǔn)數(shù)據(jù)集的采集原則校準(zhǔn)數(shù)據(jù)集是量化里最容易被輕視、對(duì)結(jié)果影響最大的環(huán)節(jié)。我的經(jīng)驗(yàn)是100到500張圖片通常夠用多樣性比數(shù)量更重要。具體原則有三條。第一條校準(zhǔn)數(shù)據(jù)必須代表部署時(shí)真實(shí)會(huì)遇到的數(shù)據(jù)分布。做工業(yè)質(zhì)檢就采樣產(chǎn)線上的真實(shí)圖片不能拿公開數(shù)據(jù)集充數(shù)做自然場景分類就覆蓋不同光照、不同分辨率、不同模糊程度。第二條不要用訓(xùn)練集用驗(yàn)證集或從完整測試分布里抽樣。訓(xùn)練集里模型的激活分布和推理分布有偏差用訓(xùn)練集校準(zhǔn)會(huì)高估實(shí)際精度。第三條如果部署場景復(fù)雜把多種場景的數(shù)據(jù)拼在一個(gè)校準(zhǔn)集里寧可每類少一點(diǎn)也要把分布邊界覆蓋到。我還遇到過一個(gè)反面案例校準(zhǔn)數(shù)據(jù)全是清晰圖像模型上線后部署環(huán)境里輸入經(jīng)常帶噪聲激活分布整體偏移真實(shí)精度比離線評(píng)測低了近兩個(gè)點(diǎn)。重新采樣了包含噪聲增強(qiáng)的校準(zhǔn)集之后問題解決。3.3 第三步跑通PTQ的標(biāo)準(zhǔn)動(dòng)作準(zhǔn)備就緒后后訓(xùn)練量化PTQ的流程非常固定我每次都是以下六步加載已完成BN折疊的模型確認(rèn)是推理模式關(guān)閉所有隨機(jī)行為。準(zhǔn)備校準(zhǔn)數(shù)據(jù)集控制在幾百張規(guī)模。在模型前向計(jì)算中插入觀察算子記錄每層激活的統(tǒng)計(jì)信息。很多框架有現(xiàn)成工具也可以用鉤子機(jī)制自己采集。跑一遍校準(zhǔn)數(shù)據(jù)收集完整統(tǒng)計(jì)后按選定的校準(zhǔn)方法計(jì)算每層的S和Z。把權(quán)重按量化公式轉(zhuǎn)成INT8激活量化參數(shù)記錄下來。導(dǎo)出量化模型做完整評(píng)估精度指標(biāo)、延遲、體積三項(xiàng)都要測。下面是一個(gè)簡化版的參數(shù)計(jì)算邏輯用來說明核心流程實(shí)際工程里可以直接用框架的量化工具def compute_scale_zero_point(min_val, max_val, bits8, symmetricFalse): # 計(jì)算縮放系數(shù)把浮點(diǎn)范圍映射到整數(shù)范圍 if symmetric: # 對(duì)稱量化取絕對(duì)值較大的邊界零點(diǎn)固定為0 abs_max max(abs(min_val), abs(max_val)) q_min -(1 (bits - 1)) q_max (1 (bits - 1)) - 1 scale abs_max / max(abs(q_min), abs(q_max)) zero_point 0 else: # 非對(duì)稱量化保留零點(diǎn)既用于非負(fù)分布也用于保存0值 q_min 0 q_max (1 bits) - 1 scale (max_val - min_val) / (q_max - q_min) zero_point round(q_min - min_val / scale) zero_point max(q_min, min(q_max, zero_point)) return scale, zero_point跑完第六步如果精度損失在可接受范圍內(nèi)PTQ就可以收工。如果掉點(diǎn)明顯進(jìn)入下面的排查鏈路逐層定位問題。3.4 第四步PTQ精度不足時(shí)升級(jí)到QATPTQ搞不定的時(shí)候就要考慮量化感知訓(xùn)練QAT。判斷標(biāo)準(zhǔn)很簡單精度指標(biāo)超過容忍線。分類任務(wù)掉1個(gè)點(diǎn)以內(nèi)我都還能接受目標(biāo)檢測的mAP掉2個(gè)點(diǎn)以上就要警惕。QAT的原理是在訓(xùn)練前向里插入偽量化算子把激活和權(quán)重先量化到INT8再反量化回浮點(diǎn)讓模型在訓(xùn)練時(shí)就看見量化誤差。反向傳播有個(gè)關(guān)鍵trickround函數(shù)的梯度幾乎處處為0直接回傳會(huì)讓模型學(xué)不動(dòng)所以用直通估計(jì)器STE把round的梯度直接透傳過去讓模型知道輸入往哪個(gè)方向變能減少量化誤差。實(shí)操上我的做法是基于預(yù)訓(xùn)練權(quán)重繼續(xù)微調(diào)不從頭訓(xùn)。偽量化只插入權(quán)重和激活優(yōu)化器直接用SGD或Adam學(xué)習(xí)率比正常訓(xùn)練小一個(gè)數(shù)量級(jí)比如3e-5起步。微調(diào)輪數(shù)不用多幾個(gè)epoch就能看到效果。有一個(gè)細(xì)節(jié)QAT過程中BN處理要格外小心先把BN統(tǒng)計(jì)量固定或者折疊后再訓(xùn)練否則BN會(huì)跟偽量化交互作用訓(xùn)練震蕩。QAT成本在于需要數(shù)據(jù)和訓(xùn)練資源至少在部分訓(xùn)練集上跑一遍周期比PTQ長很多。但精度恢復(fù)能力確實(shí)強(qiáng)我在一個(gè)檢測模型上PTQ掉了3.8個(gè)點(diǎn)QAT微調(diào)后恢復(fù)到只掉0.6個(gè)點(diǎn)差距非常大。4. 精度掉點(diǎn)排查鏈路五個(gè)高頻坑與修復(fù)方法量化掉點(diǎn)不可怕可怕的是不知道往哪里查。我踩過很多坑之后總結(jié)出一條固定的排查鏈路先確認(rèn)校準(zhǔn)數(shù)據(jù)分布再看激活離群點(diǎn)然后查敏感層最后考慮混合精度。按這個(gè)順序排查絕大多數(shù)問題都能定位。4.1 坑一校準(zhǔn)數(shù)據(jù)與真實(shí)部署分布不一致這是所有精度問題的第一嫌疑。特征是離線評(píng)測精度很好換到線上真實(shí)數(shù)據(jù)就掉或者校準(zhǔn)集上一測精度還行一換到覆蓋更廣的測試集就掉。定位方法很簡單換校準(zhǔn)集重跑一遍PTQ看精度是否恢復(fù)。如果換數(shù)據(jù)有效果問題就出在數(shù)據(jù)分布上。修復(fù)方法是重新采集有代表性的校準(zhǔn)數(shù)據(jù)必要時(shí)加入數(shù)據(jù)增強(qiáng)來覆蓋更寬分布。我在真實(shí)項(xiàng)目里見過最極端的情況僅僅是把校準(zhǔn)集從公開數(shù)據(jù)換成現(xiàn)場采集數(shù)據(jù)量化模型在線上環(huán)境的精度就恢復(fù)了兩個(gè)點(diǎn)。4.2 坑二激活值存在極端離群點(diǎn)校準(zhǔn)數(shù)據(jù)沒問題但某些層的激活范圍異常大min-max校準(zhǔn)會(huì)把量程拉得極寬導(dǎo)致正常值精度被犧牲。定位方法打印量化后每層激活的S值看有沒有某一層的S比其他層大幾個(gè)數(shù)量級(jí)。如果有基本可以鎖定是離群點(diǎn)在作祟。修復(fù)方案有三個(gè)層次。第一換百分位校準(zhǔn)把0.01%的尾部極端值裁掉第二該層單獨(dú)換熵校準(zhǔn)做更細(xì)致的截?cái)辔恢盟阉鞯谌绻x群點(diǎn)集中在個(gè)別通道考慮對(duì)該層權(quán)重啟用per-channel量化。我在一個(gè)語義分割模型上靠把激活校準(zhǔn)從min-max換成99.99百分位mIoU從掉4個(gè)點(diǎn)恢復(fù)到掉1個(gè)點(diǎn)以內(nèi)。4.3 坑三早期層與輸出層特別敏感不同層對(duì)量化的耐受程度差別很大。規(guī)律很明確網(wǎng)絡(luò)的前幾層負(fù)責(zé)提取低級(jí)特征量化誤差會(huì)沿著網(wǎng)絡(luò)逐層放大輸出層直接決定最終預(yù)測誤差沒有機(jī)會(huì)被中間層糾正。所以首層和尾層往往是精度掉點(diǎn)的重災(zāi)區(qū)。定位方法還是那句話逐層實(shí)驗(yàn)。把網(wǎng)絡(luò)分成三段只量化中間部分首尾保持FP32看精度是否恢復(fù)。我常用一個(gè)更精細(xì)的做法逐層把該層量化參數(shù)放進(jìn)去其余層保持FP32跑一遍驗(yàn)證集畫出每一層單獨(dú)量化時(shí)的精度損失曲線。損失最大的那幾層就是敏感層。修復(fù)方案就是混合精度敏感層保持FP32其余層用INT8。這樣模型體積和速度只犧牲一小部分精度卻可能完全恢復(fù)。比如一個(gè)檢測模型我只把回歸頭的前兩層保留FP32mAP就回到了FP32水平總體推理速度仍然有1.7倍左右的提升性價(jià)比極高。4.4 坑四稀疏激活與已死ReLU的誤導(dǎo)ReLU之后大量神經(jīng)元輸出為0特別是網(wǎng)絡(luò)后段更稀疏。如果某層激活分布里90%的值都是0min-max校準(zhǔn)會(huì)把有效取值范圍壓得很窄剩下那些非零值的量化粒度就粗得離譜。最直接的觀察方法統(tǒng)計(jì)校準(zhǔn)過程中每個(gè)激活張量里零值的比例超過一半就得警惕。修復(fù)思路是別讓0主導(dǎo)分布一種做法是該層換非對(duì)稱量化把零點(diǎn)偏移到合適位置另一種做法是適當(dāng)放寬截?cái)喾秶呐聽奚稽c(diǎn)零附近的精度也要保住非零值的分辨率。我在一個(gè)輕量分類網(wǎng)絡(luò)上遇到過這個(gè)問題最后一層卷積的激活零值比例超過70%百分位校準(zhǔn)配合非對(duì)稱量化精度從掉2.3個(gè)點(diǎn)恢復(fù)到掉0.4個(gè)點(diǎn)。4.5 敏感層定位逐層量化的實(shí)驗(yàn)方法論最后把這套方法總結(jié)成可復(fù)用的實(shí)驗(yàn)流程能幫你少走一半彎路先整體量化跑一遍確認(rèn)掉點(diǎn)幅度作為基準(zhǔn)。從第一層到最后一層每次只量化單層其余保持FP32記錄單層掉點(diǎn)幅度。按掉點(diǎn)幅度從大到小排序取前20%的層作為敏感層集合。把敏感層保持FP32其余層量化復(fù)測整體精度與速度。如果還有掉點(diǎn)擴(kuò)大敏感層范圍重復(fù)第4步直到找到精度與速度的平衡點(diǎn)。這個(gè)過程跑下來通常只需要幾次前向傳播成本很低但信息量非常大。我在NLP模型上用它發(fā)現(xiàn)Attention的QKV投影層是重災(zāi)區(qū)而FFN層幾乎免疫這個(gè)結(jié)論直接決定了我后續(xù)的量化方案。5. 實(shí)測收益與邊界條件哪些場景適合INT8原理和流程都清楚了最后說一組我手里的代表項(xiàng)目實(shí)測數(shù)據(jù)以及INT8在哪些場景下真的合適、哪些場景不該硬上。5.1 一組有代表性的實(shí)測數(shù)據(jù)下面是我在不同項(xiàng)目里收集到的幾組典型結(jié)果都是基于我自己的實(shí)驗(yàn)環(huán)境不代表所有硬件和框架的一致表現(xiàn)但是方向很有參考價(jià)值場景FP32大小INT8大小FP32延遲INT8延遲FP32精度INT8精度精度差圖像分類約五千萬參數(shù)200MB50MB42ms19ms91.2%90.8%-0.4%目標(biāo)檢測兩階段網(wǎng)絡(luò)140MB35MB88ms52ms47.3 mAP45.9 mAP-1.4語義分割實(shí)時(shí)網(wǎng)絡(luò)30MB7.5MB18ms9ms74.6 mIoU73.9 mIoU-0.7分類模型對(duì)量化最寬容掉點(diǎn)可以控制在0.5個(gè)點(diǎn)以內(nèi)延遲收益接近2.2倍。檢測模型因?yàn)榛貧w分支對(duì)坐標(biāo)精度敏感掉點(diǎn)更容易放大需要配合敏感層混合精度。分割模型表現(xiàn)居中。5.2 不同硬件下的速度收益差異同樣一個(gè)INT8模型在不同硬件上的收益能差出好幾倍。這個(gè)必須在選型之前就搞清楚。帶專用INT8加速指令的CPU通常是收益最大的場景卷積網(wǎng)絡(luò)能到1.5到3倍提速。這類CPU的SIMD指令寬度對(duì)INT8更友好一個(gè)時(shí)鐘周期能處理的運(yùn)算數(shù)是FP32的四倍。如果硬件不支持INT8加速指令I(lǐng)NT8模型在CPU上可能只有帶寬收益提速很少甚至沒有因?yàn)樘幚砥餍枰袸NT8數(shù)據(jù)先轉(zhuǎn)回FP32再計(jì)算白白多一次轉(zhuǎn)換開銷。GPU場景相對(duì)復(fù)雜?,F(xiàn)代GPU的FP16和FP32吞吐已經(jīng)很高部分還支持加速矩陣運(yùn)算INT8收益未必明顯有時(shí)候甚至不如直接上FP16。我個(gè)人的判斷是GPU上優(yōu)先測FP16再測INT8別默認(rèn)INT8一定最快。移動(dòng)端NPU和嵌入式加速器是最能吃INT8紅利的地方很多加速器原生只支持INT8運(yùn)算。但這里有個(gè)大坑這些硬件的約束往往很嚴(yán)格有的只支持對(duì)稱量化有的只支持per-tensor有的對(duì)零點(diǎn)偏移支持有限。設(shè)計(jì)方案之前必須先看硬件手冊(cè)按硬件約束反過來約束量化方案。5.3 量化不是銀彈什么時(shí)候該繼續(xù)用FP16有三個(gè)場景我會(huì)明確勸退INT8。第一數(shù)值動(dòng)態(tài)范圍極大的模型。比如語音波形生成的回歸任務(wù)輸出值是連續(xù)的模擬信號(hào)動(dòng)態(tài)范圍可以跨越好幾個(gè)數(shù)量級(jí)8位整數(shù)的分辨率根本不夠強(qiáng)行量化會(huì)出現(xiàn)明顯的音質(zhì)劣化。這類任務(wù)FP16往往更合適收益和風(fēng)險(xiǎn)都更可控。第二迭代式生成模型。擴(kuò)散模型這類需要多次前向迭代推理的場景量化誤差會(huì)在多次迭代中累積放大。單次迭代誤差看起來很小幾十次迭代后圖像質(zhì)量可能明顯劣化。這類場景做量化要極其謹(jǐn)慎要么做完整的QAT讓模型適應(yīng)誤差累積要么保持FP16等推理引擎原生支持更好的壓縮方案再說。第三本身就是小模型。一個(gè)只有幾MB的輕量網(wǎng)絡(luò)體積收益不明顯帶寬壓力也不大量化反而容易把本來就不多的模型容量壓得更緊。這種場景先考慮剪枝或直接用FP16別上來就量化。最后一個(gè)選型建議很樸素先跑PTQ看掉點(diǎn)是否在容忍線內(nèi)在容忍線內(nèi)就收工不在就上混合精度再不行才上QAT。這個(gè)順序能讓你用最少的成本解決絕大多數(shù)問題。我做量化做到現(xiàn)在最大的體會(huì)是它不是一個(gè)開個(gè)開關(guān)就完事的功能而是一套需要理解數(shù)值分布、硬件約束和誤差傳播的工程方法。把原理吃透把排查鏈路建好INT8就是部署工具箱里性價(jià)比最高的那把工具理解不到位就硬上它也會(huì)讓你為精度問題熬上好幾周。希望這篇能幫你把前一步走穩(wěn)。