在開始前,我們先複習一下浮點數的結構。
浮點數在計算機中的表示是基于科學計數法(Scientific Notation)的,我們知道32767這個數用科學計數法可以寫成3.2767×10^4,3.2767稱為尾數(Mantissa),4稱為指數(Exponent)。浮點數在計算機中的表示與此類似,只不過基數(Radix,也可稱進位制)是2而不是10。
而FP8是FP16的衍生產物,它包含兩種編碼格式E4M3與E5M2。對於E4M3而言,其包含4bit指數、3bit底數、以及1bit符號位元(正負號)。E5M2同理包含5bit指數位、3bit底數、1bit符號。下圖展示了FP32,FP16,FP8的格式對比:
2022年9月,NV、ARM和Intel三家公司的工程師聯合提出了一篇論文,主題是使用FP8於深度學習上--大致上是說,FP8在深度學習任務中可以取得和FP16比肩的結果,並能有效提升訓練的效率。
我們自然很容易想像,FP8和FP16相比可以提升訓練效率這件事情,畢竟相乘時運算兩端都只剩一半長度,對效率的提升是顯而易見的。而精度部分,基本上FP8和FP16就是一個兩倍的縮放,在經過完善訓練後精度損失甚小--不如說有些狀況反而不要這麼精細的表示會更有魯棒性一點。
我們知道FP8在訓練時的好處了,那麼執行時呢?和我們以往量化使用的INT8相比又有什麼不同呢?
首先,我們要先了解兩者在量化上到底有什麼不同。首先,我們很容易可以想像INT8的狀況:將原本對應到一個浮點數空間的數值「按照等分區間對應到一個整數上」。
這麼做的最大問題在於,原先浮點數對於0~1之間--也就是小數的部分佔的比例較大,因此INT8量化時需要依照原始資料,進行calibration(中文翻作校準,也有人會稱為對齊。目的是選擇原始資料中需要量化的上下限數值,超過的則直接變成上/下限值)後再進行等分對應。但即使調整,還是會損失一部分的精確度--畢竟對應的密集程度確實有所差別。
下圖是一個常見模型某一層的參數分布:
可以看到,參數確實偏向0~1之間,這時候如果單純以有數值的上下屆進行INT量化,則會使太多0~1之間的數值變成相同的對應數值;而如果校準,就會損失一些突出邊界的特徵值。
前面講過FP8基本上就是縮減一半的FP16,因此幾乎沒有對應問題,可以直接對應。而它們同樣是8bit寬的參數,理論上執行效能應該接近,這樣是否FP8是更好的選擇呢?
實際上,FP8雖然還是8bit,但它還是浮點數。這意味著原本浮點數運算的規則它也得原樣接受,而就如我們以往所知的,CPU並不精於浮點數運算,也就是實際上純CPU運行時,FP8的速度還是會輸給INT8不少。
再者,對應密集程度的差異實際上並沒有大家想得如此嚴重。在適當的校準後,INT8的表現並沒有輸給FP8太多,這又回到了量化本身就是為了犧牲精度換取速度的目的性上。
最後,分享一下個人對這兩種技術的看法。
從本鳥的觀點來看,FP8與其說是量化,更精準的說是對GPU的一種速度優化。GPU的特性使它擁有高效率的浮點數處理能力,在這狀況下將FP16變為FP8無疑可以大幅提升執行和訓練的效率。反過來說,INT8就是為了CPU的執行速度優化,當我們僅有CPU或者算力受限時,就更適合採用INT8的形式。兩者沒有絕對的優劣性,單純的應用方向不同而已。