FP8 是一種 8 位浮點數表示法,FP8 的詳細介紹可以參考鏈接nv官網介紹
FP8 采取 E4M3 和 E5M2 兩種表示方式,其中 E 代表指數位(Exponent),M 代表尾數位(Mantissa)。在表示范圍內,E4M3 更精準,而 E5M2 有更寬的動態范圍。與傳統的 FP16(16 位浮點數)和 FP32(32 位浮點數)相比,它顯著減少了存儲,提高了計算吞吐。
小數的二進制表示
目前C/C++編譯器標準都遵照IEEE制定的浮點數表示法來進行float,double運算。這種結構是一種科學計數法,用符號、指數和尾數來表示,底數定為2——即把一個浮點數表示為尾數乘以2的指數次方再添上符號。下面是具體的規格:
符號位 階碼 尾數 長度
float 1 8 23 32
double 1 11 52 64
對float來說,按IEEE標準 階碼一共8位,可以表示范圍是-128 ~ 127。因為指數可以為負,為了便于計算,規定都先加上127(2^7-1)
對double來說,按IEEE標準 階碼一共11位,可以表示范圍是-1024 ~ 1023。因為指數可以為負,為了便于計算,規定都先加上1023(2^10-1)
規格化的二進制浮點數的格式一般為:(-1)^S × M × 2^E。
例一:
已知:double類型38414.4。
求:其對應的二進制表示。
分析:double類型共計64位,折合8字節。由最高到最低位分別是第63、62、……、0位:
最高位63位是符號位,1表示該數為負,0表示該數為正;
62-52位,一共11位是指數位;
51-0位,一共52位是尾數位。
步驟:按照IEEE浮點數表示法,下面先把38414.4轉換為十六進制數。
把整數部和小數部分開處理:整數部直接化十六進制:960E。小數的處理:
0.4=0.5*0+0.25*1+0.125*1+0.0625*0+……
實際上這永遠算不完!這就是著名的浮點數精度問題。所以直到加上前面的整數部分算夠53位就行了。隱藏位技術:最高位的1不寫入內存(最終保留下來的還是52位)。
如果你夠耐心,手工算到53位那么因該是:38414.4(10)=1001011000001110.0110011001100110011001100110011001100(2)
科學記數法為:1.001011000001110 0110011001100110011001100110011001100,右移了15位,所以指數為15。或者可以如下理解:
1.001011000001110 0110011001100110011001100110011001100×2^15
于是來看階碼,按IEEE標準一共11位,可以表示范圍是-1024 ~ 1023。因為指數可以為負,為了便于計算,規定都先加上1023(2^10-1),在這里,階碼:15+1023=1038。1038的二進制表示為:100 00001110;
符號位:因為38414.4為正對應 為0;
合在一起(注:尾數二進制最高位的1不要):
01000000 11100010 11000001 110 01100 11001100 11001100 11001100 11001100
例二:
已知:整數3490593(16進制表示為0x354321)。
求: 其對應的浮點數3490593.0的二進制表示。
解法如下:
先求出整數3490593的二進制表示:
Hex: 3 5 4 3 2 1 (十六進制表示)
Bin: 0011 0101 0100 0011 0010 0001 (二進制表示)
即: 1.1010101000011001000012×221
可見,從左算起第一個1后有21位,我們將這21為作為浮點數的小數表示,單精度浮點數float由符號位1位,指數域位k=8位,小數域位(尾數)n=23位構成,因此對上面得到的21位小數位我們還需要補上2個0才湊夠23,得到浮點數的小數域表示為:
1 0101 0100 0011 0010 0001 00 共23個
將148轉為二進制表示為10010100,加上符號位0,最后得到二進制浮點數表示01001010010101010000110010000100,其16進制表示為:
H: 4 A 5 5 0 C 8 4
B: 0100 1010 0101 0101 0000 1100 1000 0100
這就是浮點數3490593.0(0x4A550C84)的二進制表示。
例三:
0.5的二進制形式是0.1
它用浮點數的最終形式寫出來是如下格式
0 01111110 00000000000000000000000
符號位 階碼 小數位
正數符號位為0,負數符號位為1。
階碼是以2為底的指數。
小數位表示小數點后面的數字。
下面我們來分析一下0.5最終是如何寫成0 01111110 00000000000000000000000
首先0.5是正數所以符號位為0
再來看階碼部分,由于0.5的二進制數是0.1,而0.1是1.0*2^(-1),
注:如果只有小數部分,例如0.1,那么需要右移小數點,所以0.1是1.0*2^(-1). 再比如右移3位才能放到第一個1的后面(0.001是1.0*2^(-3)), 階碼就是127-3=124.
要把二進制數變成(1.f)*2^(exponent)的形式,其中exponent是指數;
又由于階碼有正負之分所以, 階碼=127+exponent;即階碼=127+(-1)=126 即 01111110
余下的小數位為二進制小數點后面的數字,即00000000000000000000000
由以上分析得0.5的浮點數存儲形式為0 01111110 00000000000000000000000
例四
(20.59375)10 =(10100.10011 )2
首先分別將整數和分數部分轉換成二進制數:
20.59375=10100.10011
然后 左移移動小數點,使其在第1,2位之間
10100.10011=1.010010011×2^4 即e=4
于是得到:
S=0, E=4+127=131, M=010010011
最后得到32位浮點數的二進制存儲格式為:
0 131 010010011
0 1000 0011 010010011
0100 1001 1010 0100 1100 0000 0000 0000=(41A4C000)16