模型量化
参考
浮点和整数的存储
不同数据类型在机器中的存储大小
type | size | min | max |
---|---|---|---|
char | 1 | -128 | 127 |
unsigned char | 1 | 0 | 255 |
short int | 2 | -32768 | 32767 |
unsigned short int | 2 | 0 | 63535 |
int | 4 | -2147483648 | 2147483647 |
unsigned int | 4 | 0 | 4294967295 |
long int | 8 | -2147483648 | 2147483647 |
unsigned long int | 8 | 0 | 4294967295 |
float | 4 | ||
double | 8 |
浮点数的表示
IEEE浮点标准用 的形式来表述一个浮点数:
- : 符号(sign)s 决定这个浮点数的正(s=0)负(s=1)
- : 有效数(significant)M 是一个二进制小数,它的范围在 或者 之间
- : 指数(exponent)E 是 2 的幂(可能是符数,因为 E 的计算中有个bias),它的作用是对浮点数进行加权
浮点数的位(bits)被划分为三个域,以编码这三个值
- 1 位单独的符号位 直接编码符号
- k 位的指数域 编码指数
- n 位的小数域 编码有效数 (但是被编码的值也依赖于指数域的值是否为 0)
在单精度浮点数(float)中,,产生一个 32 位的表示
在双精度浮点数(double)中,,产生一个 64 位的表示
规格化的值
当 exp 的位模式既不全位 0 (数值0), 也不全为 1 (单精度数值为 2^8 - 1 = 255, 双精度数值为 2^11 - 1 = 2047) 时, 对应的就是规格化的表示, 即 .
在规格化的表示中, 指数域被进行偏置 (biasd), 用来表示有符号的整数. 例如 表示一个浮点数的指数域, 它对应一个整数值 , 令 (单精度是 127, 双精度是 1023), , 由此产生的指数的取值范围: 单精度 , 双精度 . 另外注意在规格化的表示中, 指数的位值不能全 0 (单精度: -127, 双精度: -1023)和全 1 (单精度: +128, 双精度: +1024).
小数域 frac 被解释为小数部分的值, 例如 可以表示小数 . 而我们将有效数 M 定义为 , 我们总能调整指数 E, 使得有效数 M 的范围在 之中.
不同的float标准
浮点数格式:FP64, FP32, FP16, BFLOAT16, TF32之间的相互区别
bfloat16 floating-point format | wiki
bfloat16 其中的 b 指代 Google Brain
为什么要选择 bf16 进行深度学习的权重类型
bf16 拥有和 fp16 一样的大小 (2bytes), 相比于 fp32 (4bytes) 占用更少的内存, 所以在读取和存储的时候效率更高.
bf16 的指数域为 8 个 bits, 拥有和 fp32 一样的表示范围. 相比于 bp16, fp16 只有 5 bits 的指数域, 它所能表示的范围更小, 在训练过程中参数和结果有可能溢出. 当然, bp16 为了获得更大的表示范围为指数域分配了更多的比特位, 导致它的小数域只有 7 bits, 相比 fp16 的 10 bits 的小数域, bp16 所能表示的精度更低.
Format | Bits | Sign | Exponent | Bias | Range | Fraction |
---|---|---|---|---|---|---|
FP32 | 32 | 1 | 8 | 127 | 23 | |
FP16 | 16 | 1 | 5 | 15 | 10 | |
BF16 | 16 | 1 | 8 | 127 | 7 |
混合精度训练指的是使用FP32作为主权重,而在进行前向和后向传播时使用FP16/BF16来提升训练速度,最后在梯度更新阶段再使用FP16/BF16梯度更新FP32主权重。