Pytorch基于Apex的混合精度加速
Pytorch >= 1.6.0
pytorch1.6开始官方支持了混合精度训练。使用方法如下:
1 | from torch.cuda.amp import autocast as autocast, GradScaler |
Pytorch < 1.6.0
pytorch1.6版本前需要配合第三方插件使用混合精度。
Apex
Apex是由Nvidia维护的一个支持混合精度分布式训练的第三方Pytorch扩展。可以用短短三行代码就能实现不同程度的混合精度加速,使训练时间和显存占用直接缩小一半。
安装
以下是安装 apex 的方法. apex克隆在哪里都无所谓
1 | git clone https://github.com/NVIDIA/apex |
以下代码用于验证是否安装成功:
1 | try: |
卸载命令为:
1 | pip uninstall apex |
支持列表
判断你的GPU是否支持FP16:支持的有拥有Tensor Core的GPU(2080Ti、Titan、Tesla等),不支持的(Pascal系列)就不建议折腾了。
如果你的GPU是以下GPU的其中一种: 请调整nvcc与pytorch.cuda至10.0
1 | GeForce GTX 1650 |
如果你打算调整Pytorch Version来适应APEX(推荐)
首先用 nvcc --version
命令调查你的nvcc版本
1 | nvcc: NVIDIA (R) Cuda compiler driver |
再进入python看看pytorch cuda版本
1 | >>> torch.version.cuda |
问题解决
3090ti自带cuda为11.1,但是并没有匹配的torch版本,这里为了安上apex,可以通过修改setup.py
尝试禁用次要版本检查。
找到如下函数,注释掉原语句,返回空值:
1 | def check_cuda_torch_binary_vs_bare_metal(cuda_dir): |
修改后,重新安装apex即可:
1 | pip install -v --no-cache-dir --global-option="--cpp_ext" --global-option="--cuda_ext" ./ |
我在安装了带有cuda-11.0的pytorch的同时,针对整个系统的cuda-11.1成功构建了apex!
使用
导入包:
1 | from apex import amp |
在你创建后net(model)和optimizer后添加代码(注意顺序):
1 | net = net.cuda() |
然后把你的loss.backward()换成 :
1 | with amp.scale_loss(loss, optimizer) as scaled_loss: |
如果你有用Pytorch自带的BCELoss或F.binary_cross_entropy, 请把他们替换成BCEWithLogitsLoss或F.binary_cross_entropy_with_logists并用logists 作为输入.
说明
opt level
其中只有一个opt_level需要用户自行配置:
oe:纯FP32训练,可以作为accuracy的baseline;
o1:混合精度训练(推荐使用),根据黑白名单自动决定使用FP16(GEMM,卷积)还是FP32(Softmax)进行计算。
02:“几乎FP16”混合精度训练,不存在黑白名单,除了Batch norm,几乎都是用FP16计算。
o3:纯FP16训练,很不稳定,但是可以作为speed的baseline;
动态损失放大(Dynamic Loss Scaling)
AMP默认使用动态损失放大,为了充分利用FP16的范围,缓解舍入误差,尽量使用最高的放大倍($2^{24}$),如果产生了上溢出(Overflow),则跳过参数更新,缩小放大倍数使其不溢出,在一定步数后(比如2000步)会再尝试使用大的scale来充分利用FP16的范围:
优势
- 减少显存占用 现在模型越来越大,当你使用Bert这一类的预训练模型时,往往显存就被模型及模型计算占去大半,当想要使用更大的Batch Size的时候会显得捉襟见肘。由于FP16的内存占用只有FP32的一半,自然地就可以帮助训练过程节省一半的显存空间。
- 加快训练和推断的计算 与普通的空间时间Trade-off的加速方法不同,FP16除了能节约内存,还能同时节省模型的训练时间。在大部分的测试中,基于FP16的加速方法能够给模型训练带来多一倍的加速体验(爽感类似于两倍速看肥皂剧)。
- 张量核心的普及 硬件的发展同样也推动着模型计算的加速,随着Nvidia张量核心(Tensor Core)的普及,16bit计算也一步步走向成熟,低精度计算也是未来深度学习的一个重要趋势,再不学习就out啦。