当前的深度学习框架大都采用的都是fp32来进行权重参数的存储,比如Python float的类型为双精度浮点数fp64,pytorch Tensor的默认类型为单精度浮点数fp32。随着模型越来越大,加速训练模型的需求就产生了。在深度学习模型中使用fp32主要存在几个问题,第一模型尺寸大,训练的时候对显卡的显存要求高;第二模型训练速度慢;第三模型推理速度慢。其解决方案就是使用低精度计算对模型进行优化。本文主要讲解几种优化显存存储的方法。
1. fp32、fp16、bf16混合精度训练
- FP32 是单精度浮点数,1位符号位,8位指数,23位表示小数,总共32位
- BF16 是对FP32单精度浮点数截断数据,即用8bit 表示指数,7bit 表示小数
- FP16 半精度浮点数,用5bit 表示指数,10bit 表示小数;
与32位相比,采用BF16/FP16吞吐量可以翻倍,内存需求可以减半。但是这两者精度上差异不一样,BF16 可表示的整数范围更广泛,但是尾数精度较小;FP16 表示整数范围较小,但是尾数精度较高。
1.1 混合精度训练
直接使用半精度进行计算会导致的两个问题的处理:舍入误差(Rounding Error)和溢出错误(Grad Overflow / Underflow)
-
舍入误差
float16 的最大舍入误差约为 2 − 10 ~2 ^{-10} 2−10,比 float32 的最大舍入误差