)
1. 為什么 W4A8 是當下大模型推理的甜點區(qū)第一次看到“Kimi 2.7 Moe 從 4bit 存儲到 INT8 拆解”這個標題很多人會以為只是把權重壓到 4bit 就完事了。實際做過 MoE 推理優(yōu)化的人都知道真正難的不是“存得下”而是“算得快、算得準、顯存還省”。W4A8 這個組合——權重 4bit 存儲、激活 INT8 計算——恰好卡在了一個非常微妙的平衡點上顯存占用接近純 4bit 方案而計算吞吐又比 W4A16 高出一大截。先把概念理清楚。W4A8 里的 W 指 Weight權重A 指 Activation激活。W4 表示權重以 4bit 精度存儲A8 表示激活值在計算時量化到 INT8。注意這里有個關鍵區(qū)別權重是“存儲精度”激活是“計算精度”。權重 4bit 存下來之后在 kernel 內(nèi)部會被反量化到更高精度參與計算而激活走 INT8 是為了吃到整數(shù)運算單元的吞吐紅利。為什么不是 W4A4因為激活對精度太敏感了。激活值在 MoE 里經(jīng)過 router 的 softmax、專家層的 GeLU/SiLU 之后動態(tài)范圍變化劇烈4bit 激活會直接把模型質(zhì)量打崩。為什么不是 W8A8因為權重 8bit 存儲省不下多少顯存MoE 模型動輒幾百 GB 的權重8bit 和 16bit 的差距在部署成本上是數(shù)量級的。所以 W4A8 是工程上反復權衡后的結(jié)果。這里要區(qū)分幾個容易混淆的精度概念。FP32 是 32 位浮點1 位符號 8 位指數(shù) 23 位尾數(shù)動態(tài)范圍極大但算力需求最高。FP16 是 16 位浮點1510動態(tài)范圍夠用但尾數(shù)精度有限。BF16 是 187指數(shù)位和 FP32 一樣動態(tài)范圍大但尾數(shù)精度低適合訓練。INT8 是 8 位整數(shù)沒有指數(shù)位靠 scale 和 zero_point 把浮點映射到整數(shù)區(qū)間算力需求最低、吞吐最高。FP8 則是 143 或 152介于 FP16 和 INT8 之間近兩年在訓練側(cè)很火但推理側(cè)生態(tài)還不如 INT8 成熟。提示W(wǎng)4A8 不是“權重和激活都壓到 4bit/8bit 就完事”權重的 4bit 是存儲格式計算時通常要反量化激活的 INT8 是計算格式需要 per-token 或 per-channel 的動態(tài)量化。兩者是兩套獨立的量化邏輯不能混為一談。MoE 模型為什么特別適合 W4A8因為 MoE 的參數(shù)量大但激活參數(shù)量小。以 Kimi 2.7 Moe 這類架構為例總參數(shù)量可能幾百 B但每個 token 只激活其中一小部分專家。這意味著權重的存儲開銷是主要矛盾而激活的計算量相對可控。W4 把權重存儲壓到極致A8 保證激活計算不拖后腿這個組合對 MoE 來說幾乎是量身定做的。2. 4bit 權重存儲的三種主流格式與選擇邏輯權重壓到 4bit不是簡單地把 FP16 截斷。4bit 能表示的只有 16 個離散值怎么把這 16 個值映射到原始權重分布上直接決定了量化后的模型質(zhì)量。目前工程上主流有三種格式GPTQ 風格的 group-wise 對稱量化、AWQ 風格的激活感知量化、以及 NF4/FP4 這類非線性格式。2.1 GPTQ 的 group-wise 量化到底在做什么GPTQ 的核心思路是逐層做最小二乘誤差補償。它把權重矩陣按列分組每組比如 128 個元素共享一個 scale 和 zero_point然后把這組權重映射到 4bit 整數(shù)區(qū)間。反量化時用w (q - zero_point) * scale還原。group size 越小量化誤差越小但 scale 的存儲開銷越大。128 是常見的折中64 更精細但元數(shù)據(jù)翻倍。這里有個實操細節(jié)GPTQ 量化時用的是校準集calibration set的激活統(tǒng)計而不是原始權重分布。因為權重的量化誤差最終要通過激活體現(xiàn)出來所以校準集的質(zhì)量直接影響量化效果。我一般會用 128 到 512 條覆蓋多領域的樣本做校準太少會導致某些專家層的量化誤差被低估。2.2 AWQ 為什么在 MoE 上更穩(wěn)AWQ 的出發(fā)點和 GPTQ 不同。它觀察到權重里有一部分“重要通道”對激活影響特別大如果這些通道被量化誤差污染模型質(zhì)量會明顯下降。所以 AWQ 會先識別這些重要通道然后在量化時對它們做保護——要么保留更高精度要么在 scale 上做補償。MoE 模型里這個特性尤其明顯。不同專家的權重分布差異很大有些專家處理的是高頻 token激活值大有些專家處理長尾 token激活值小。如果統(tǒng)一用一套量化參數(shù)長尾專家的質(zhì)量會先崩。AWQ 的 per-channel 保護機制在 MoE 上通常比 GPTQ 更穩(wěn)代價是量化過程更慢、實現(xiàn)更復雜。2.3 NF4 和 FP4 的適用邊界NF4Normal Float 4是 QLoRA 里提出的格式假設權重近似正態(tài)分布把 4bit 的 16 個值按正態(tài)分布的分位數(shù)放置。FP4 則是標準的 4 位浮點1 位符號 2 位指數(shù) 1 位尾數(shù)動態(tài)范圍比 INT4 大但精度低。這兩種格式在 MoE 推理里用得相對少因為它們的反量化 kernel 優(yōu)化不如 INT4 成熟。但在顯存極度受限、且能接受一定質(zhì)量損失的場景下NF4 是個可選項。我的經(jīng)驗是如果目標是生產(chǎn)環(huán)境的高吞吐推理優(yōu)先選 INT4 group-wise如果是實驗性質(zhì)、追求極致顯存壓縮可以試 NF4。格式映射方式優(yōu)點缺點適用場景INT4 group-wise線性對稱/非對稱kernel 成熟、吞吐高需要 scale 元數(shù)據(jù)生產(chǎn)推理首選NF4正態(tài)分位數(shù)低比特下質(zhì)量好kernel 優(yōu)化少實驗、顯存極限FP4浮點映射動態(tài)范圍大精度低、生態(tài)弱研究性質(zhì)AWQ INT4激活感知保護MoE 上質(zhì)量穩(wěn)量化慢、實現(xiàn)復雜質(zhì)量敏感場景注意4bit 存儲的權重在加載后通常要先反量化成 FP16 或 BF16 才能參與矩陣乘。如果 kernel 支持“權重 4bit 直接參與 INT8 計算”的融合反量化那才是真正的 W4A8 加速。否則反量化本身的開銷會吃掉一部分收益。3. 激活 INT8 量化的動態(tài)范圍陷阱權重 4bit 是靜態(tài)的量化一次就固定了。激活 INT8 是動態(tài)的每個 token、每個 batch 的激活分布都不一樣。這是 W4A8 里最容易翻車的地方。3.1 per-tensor、per-token、per-channel 怎么選激活量化的粒度直接決定精度和開銷。per-tensor 是整個張量共享一個 scale開銷最小但精度最差遇到激活值分布不均時會大量截斷。per-token 是每個 token 一個 scale精度好很多開銷也可接受是目前 LLM 推理的主流選擇。per-channel 是每個通道一個 scale精度最好但開銷大通常只在權重側(cè)用。在 MoE 里激活量化還要考慮專家路由的影響。同一個 token 被路由到不同專家后激活分布可能完全不同。如果所有專家共享一套激活量化參數(shù)某些專家的激活會被過度壓縮。更穩(wěn)的做法是每個專家維護獨立的激活 scale但這會帶來額外的元數(shù)據(jù)管理和 kernel 復雜度。3.2 校準集與動態(tài)量化的取舍激活量化有兩種模式靜態(tài)量化和動態(tài)量化。靜態(tài)量化用校準集預先統(tǒng)計激活范圍推理時直接用固定 scale動態(tài)量化在推理時實時統(tǒng)計當前 batch 的激活范圍再算 scale。靜態(tài)量化快但校準集覆蓋不到的長尾輸入會掉點。動態(tài)量化準但每次都要做 reduce 操作有額外開銷。我的經(jīng)驗是prefill 階段用動態(tài)量化因為序列長、激活分布變化大decode 階段用靜態(tài)量化因為單 token、分布穩(wěn)定。很多推理框架已經(jīng)支持這種混合模式。3.3 激活異常值的處理LLM 的激活里存在少量“異常值”outlier數(shù)值可能是正常值的幾十倍。這些異常值如果直接參與 INT8 量化會把 scale 拉得很大導致正常值全部被壓到很小的整數(shù)區(qū)間精度損失嚴重。常見的處理方式有三種一是用 per-token 量化把異常值隔離在單個 token 內(nèi)二是對異常值通道做特殊處理比如保留 FP16三是用 SmoothQuant 這類方法把激活的難度遷移一部分到權重上。在 W4A8 場景下因為權重已經(jīng)是 4bit 了遷移空間有限所以更依賴 per-token 量化和異常值通道保護。# 激活 per-token INT8 量化的簡化邏輯 def quantize_activation_int8(x, eps1e-8): # x: [batch, seq, hidden] # 每個 token 計算自己的 scale abs_max x.abs().amax(dim-1, keepdimTrue) # [batch, seq, 1] scale abs_max / 127.0 eps q torch.round(x / scale).clamp(-128, 127).to(torch.int8) return q, scale def dequantize_activation_int8(q, scale): return q.to(torch.float16) * scale提示激活量化里的 zero_point 在對稱量化下是 0非對稱量化下需要額外計算。LLM 激活通常近似對稱分布所以對稱量化夠用還能省掉 zero_point 的存儲和計算。4. MoE 專家層的 W4A8 拆解實操MoE 的推理路徑和 dense 模型不同token 先過 router 算出門控權重再被分發(fā)到 top-k 個專家專家各自計算后再加權合并。W4A8 在每個環(huán)節(jié)的落地方式都不一樣。4.1 Router 和 Gate 的精度策略Router 的輸出是門控權重決定 token 去哪些專家。這部分計算量小但對精度敏感——如果 router 量化誤差大token 可能被路由到錯誤的專家后續(xù)再準也沒用。所以 router 和 gate 通常保留 FP16 或 BF16不參與 W4A8 量化。我見過有人為了省顯存把 router 也量化了結(jié)果 top-k 選擇頻繁抖動模型輸出質(zhì)量斷崖式下跌。這個坑沒必要踩router 的參數(shù)量在 MoE 里占比極小保留高精度的收益遠大于那點顯存。4.2 專家權重的 4bit 分組量化每個專家的權重矩陣獨立做 4bit group-wise 量化。這里的關鍵是 group size 和 scale 精度的選擇。group size 128 是常見起點scale 用 FP16 存儲。如果顯存實在緊張group size 可以放到 256但質(zhì)量會掉一點。專家權重的量化順序也有講究。建議先量化所有專家的權重再統(tǒng)一做校準和誤差評估。因為不同專家的權重分布差異大逐個量化容易在后期發(fā)現(xiàn)前面專家的參數(shù)需要調(diào)整返工成本高。4.3 專家激活的 INT8 量化與合并專家計算完成后輸出需要加權合并。合并前的激活是 INT8合并時通常要反量化回 FP16 再乘門控權重。如果門控權重也是 FP16那合并就是 FP16 運算。這里有個優(yōu)化點如果 top-k 的門控權重能提前量化到 INT8合并可以在整數(shù)域完成但精度損失需要評估。實際部署里我傾向于合并階段用 FP16因為合并后的結(jié)果要進入下一層精度損失會累積。省這一步的計算不值得。4.4 一個完整的 W4A8 推理流程把上面的環(huán)節(jié)串起來一個 token 在 MoE 層的 W4A8 推理流程大致是輸入激活FP16進入 routerrouter 用 FP16 計算門控權重和 top-k 索引。激活做 per-token INT8 量化得到 INT8 激活和 scale。根據(jù) top-k 索引把 INT8 激活分發(fā)到對應專家。專家權重以 4bit 存儲kernel 內(nèi)部反量化到 INT8 或 FP16與 INT8 激活做矩陣乘。專家輸出反量化回 FP16乘以門控權重累加合并。合并結(jié)果進入下一層。這個流程里第 4 步是性能關鍵。如果 kernel 能把“4bit 權重反量化 INT8 矩陣乘”融合在一起吞吐會非??捎^。如果反量化和矩陣乘是分開的中間還要寫回顯存收益就打折了。5. HIP 后端上的 kernel 適配與性能驗證標題里提到了 HIP說明這套 W4A8 方案是在 AMD GPU 生態(tài)上落地的。HIP 的編程模型和 CUDA 類似但指令集、warp 調(diào)度、內(nèi)存層次都有差異直接照搬 CUDA kernel 往往跑不出預期性能。5.1 HIP 上 INT8 矩陣乘的指令選擇AMD GPU 的 INT8 矩陣乘通常走v_dot系列指令或 MFMAMatrix Fused Multiply-Add指令。不同架構支持的指令不同比如 CDNA 架構的 MFMA 對 INT8 有專門優(yōu)化。寫 kernel 前要先確認目標架構支持哪些指令再決定數(shù)據(jù)布局。數(shù)據(jù)布局上INT8 矩陣乘通常要求權重按特定 tile 格式排列才能讓 MFMA 指令高效讀取。4bit 權重的反量化也要配合這個布局否則反量化后的數(shù)據(jù)還要重排開銷很大。5.2 4bit 權重反量化的內(nèi)存訪問優(yōu)化4bit 權重在顯存里是緊湊存儲的兩個 4bit 值打包在一個 byte 里。反量化時要先解包再乘 scale。這個過程的瓶頸往往不在計算而在內(nèi)存訪問——如果解包后的數(shù)據(jù)要寫回顯存再讀帶寬就浪費了。優(yōu)化思路是讓反量化和矩陣乘在同一個 kernel 里完成反量化結(jié)果直接進寄存器或 LDSLocal Data Share不落顯存。HIP 里可以用__shared__或 LDS 來緩存反量化后的權重 tile減少全局內(nèi)存訪問。5.3 實測性能對比與瓶頸定位驗證 W4A8 效果時我一般會對比三組數(shù)據(jù)FP16 基線、W8A8、W4A8。關注兩個指標吞吐tokens/s和顯存占用。理想情況下W4A8 的吞吐應該比 W8A8 高 20% 到 40%顯存占用比 W8A8 低 40% 左右。如果吞吐沒達到預期先查是不是反量化開銷太大。用 profiler 看 kernel 時間分布如果反量化 kernel 占比超過 15%說明融合沒做好。如果矩陣乘 kernel 本身慢查指令選擇和數(shù)據(jù)布局。如果顯存占用沒降下來查 scale 元數(shù)據(jù)是不是存太多了——group size 太小會導致 scale 數(shù)量爆炸。配置權重顯存激活顯存吞吐相對 FP16質(zhì)量損失FP16100%100%1.0x基線W8A850%50%1.3-1.6x很小W4A825%50%1.5-2.0x可控W4A425%25%1.8-2.2x明顯注意上表的吞吐是理想值實際取決于 kernel 實現(xiàn)和硬件。如果反量化沒融合W4A8 的吞吐可能還不如 W8A8因為反量化本身有開銷。6. 量化質(zhì)量評估怎么判斷 W4A8 有沒有把模型搞壞量化做完不是終點質(zhì)量評估才是。W4A8 的質(zhì)量損失主要來自兩處權重 4bit 的量化誤差和激活 INT8 的量化誤差。兩者疊加可能在某些任務上放大。6.1 困惑度之外還要看什么困惑度PPL是最常用的量化評估指標但它對長尾任務不敏感。我一般會加三組測試一是標準 PPL看整體質(zhì)量二是下游任務準確率比如問答、摘要、代碼生成三是長文本一致性看模型在長上下文里會不會“跑偏”。MoE 模型還要特別關注專家利用率。如果量化后某些專家的激活值被過度壓縮router 可能會減少對這些專家的路由導致專家利用率下降。這不會直接體現(xiàn)在 PPL 上但會影響模型的表達能力。6.2 分層敏感度分析不是所有層對量化的敏感度都一樣。通常 embedding 層、router、最后的輸出層對精度最敏感中間專家層的容忍度較高。做分層敏感度分析的方法是逐層替換成量化版本看 PPL 變化。變化大的層保留高精度變化小的層放心量化。這個分析在 MoE 上尤其值得做因為專家層數(shù)量多如果能把大部分專家層量化、少數(shù)敏感層保留整體收益很可觀。6.3 量化誤差的累積與補償W4A8 的誤差會在層間累積。如果每層都有微小誤差幾十層下來可能就明顯了。補償?shù)乃悸酚袃煞N一是量化感知訓練QAT在訓練時模擬量化誤差讓模型學會適應二是訓練后補償PTQ用校準數(shù)據(jù)做局部微調(diào)。QAT 效果最好但成本高需要重新訓練。PTQ 成本低但補償能力有限。實際項目里如果 W4A8 的 PPL 損失在 2% 以內(nèi)通常直接上 PTQ如果超過 5%就要考慮 QAT 或者調(diào)整量化配置了。7. 踩過的坑與實戰(zhàn)經(jīng)驗說幾個我在 W4A8 落地過程中真實踩過的坑都是文檔里不會寫的。第一個坑是 group size 設太小。一開始為了追求質(zhì)量把 group size 設成 32結(jié)果 scale 元數(shù)據(jù)占了大量顯存整體顯存占用比預期高了 30%。后來改成 128質(zhì)量只掉了不到 0.5%顯存省了一大截。group size 不是越小越好要算總賬。第二個坑是激活量化用了 per-tensor。在 prefill 階段不同位置的激活分布差異極大per-tensor 直接把長序列后半段的激活壓沒了。改成 per-token 后長文本質(zhì)量立刻恢復。這個坑在短序列測試時發(fā)現(xiàn)不了一定要用長文本驗證。第三個坑是 HIP kernel 的數(shù)據(jù)布局沒對齊。4bit 權重解包后的 tile 布局和 MFMA 指令要求的布局不一致導致每次矩陣乘前都要重排性能比預期低了 40%。后來重寫了反量化 kernel讓解包直接輸出目標布局性能才上來。第四個坑是忽略了 router 的精度。有次為了省顯存把 router 也量化了結(jié)果 top-k 選擇在相鄰 token 間頻繁跳變生成文本的連貫性明顯下降。router 那點參數(shù)量不值得省保留 FP16 是最穩(wěn)的。提示W(wǎng)4A8 的調(diào)優(yōu)是個系統(tǒng)工程不要指望一次配置就到位。建議先跑通 FP16 基線再逐步加量化每加一步都做質(zhì)量評估這樣才能定位問題出在哪個環(huán)節(jié)。8. 從 W4A8 繼續(xù)往下走的方向W4A8 不是終點。往更激進的量化走有 W4A4、W3A8 這些方向但質(zhì)量風險更大。往更穩(wěn)的方向走有 W4A16、W8A8質(zhì)量好但收益小。W4A8 目前是收益和風險的平衡點。如果要在 W4A8 基礎上繼續(xù)優(yōu)化我建議從三個方向入手一是 kernel 融合把反量化、矩陣乘、激活量化盡量融到一個 kernel 里減少顯存往返二是專家粒度的量化策略不同專家用不同的 group size 和量化格式把敏感專家保護起來三是動態(tài)精度切換根據(jù)輸入難度動態(tài)決定用 W4A8 還是 W8A8簡單輸入走激進量化難輸入走保守量化。MoE 架構本身還在演進Kimi 2.7 這類模型的專家路由策略、專家數(shù)量、激活比例都在變。W4A8 的具體配置也要跟著調(diào)沒有一勞永逸的參數(shù)。我的習慣是每換一個模型先做一輪敏感度分析再定量化方案這樣最穩(wěn)。