网站做三方登陆需要注册公司不,seo推广名词解释,课程网站模板,网站建设致谢使用Apex进行混合精度训练
转自#xff1a;https://fyubang.com/2019/08/26/fp16/
你想获得双倍训练速度的快感吗#xff1f; 你想让你的显存空间瞬间翻倍吗#xff1f; 如果我告诉你只需要三行代码即可实现#xff0c;你信不#xff1f;
在这篇博客里#xff0c;瓦砾…使用Apex进行混合精度训练
转自https://fyubang.com/2019/08/26/fp16/
你想获得双倍训练速度的快感吗 你想让你的显存空间瞬间翻倍吗 如果我告诉你只需要三行代码即可实现你信不
在这篇博客里瓦砾会详解一下混合精度计算Mixed Precision并介绍一款Nvidia开发的基于PyTorch的混合精度训练加速神器—Apex最近Apex更新了API可以用短短三行代码就能实现不同程度的混合精度加速训练时间直接缩小一半。
话不多说直接先教你怎么用。
PyTorch实现
from apex import amp
model, optimizer amp.initialize(model, optimizer, opt_levelO1) # 这里是“欧一”不是“零一”
with amp.scale_loss(loss, optimizer) as scaled_loss:scaled_loss.backward()对就是这么简单如果你不愿意花时间深入了解读到这基本就可以直接使用起来了。
但是如果你希望对FP16和Apex有更深入的了解或是在使用中遇到了各种不明所以的“Nan”的同学可以接着读下去后面会有一些有趣的理论知识和瓦砾最近一个月使用Apex遇到的各种bug不过当你深入理解并解决掉这些bug后你就可以彻底摆脱“慢吞吞”的FP32啦。
理论部分
为了充分理解混合精度的原理以及API的使用先补充一点基础的理论知识。
1. 什么是FP16
半精度浮点数是一种计算机使用的二进制浮点数数据类型使用2字节16位存储。下图是FP16和FP32表示的范围和精度对比。 其中sign位表示正负exponent位表示指数2n−151(n0)2n−151(n0)fraction位表示的是分数m1024m1024。其中当指数为零的时候下图加号左边为0其他情况为1。下图是FP16表示范例。 2. 为什么需要FP16
在使用FP16之前我想再赘述一下为什么我们使用FP16。
减少显存占用 现在模型越来越大当你使用Bert这一类的预训练模型时往往显存就被模型及模型计算占去大半当想要使用更大的Batch Size的时候会显得捉襟见肘。由于FP16的内存占用只有FP32的一半自然地就可以帮助训练过程节省一半的显存空间。加快训练和推断的计算 与普通的空间时间Trade-off的加速方法不同FP16除了能节约内存还能同时节省模型的训练时间。在大部分的测试中基于FP16的加速方法能够给模型训练带来多一倍的加速体验爽感类似于两倍速看肥皂剧。张量核心的普及 硬件的发展同样也推动着模型计算的加速随着Nvidia张量核心Tensor Core的普及16bit计算也一步步走向成熟低精度计算也是未来深度学习的一个重要趋势再不学习就out啦。
3. FP16带来的问题量化误差
这个部分是整个博客最重要的理论核心。 讲了这么多FP16的好处那么使用FP16的时候有没有什么问题呢当然有。FP16带来的问题主要有两个1. 溢出错误2. 舍入误差。 溢出错误Grad Overflow / Underflow 由于FP16的动态范围6×10−8∼655046×10−8∼65504比FP32的动态范围1.4×10−45∼1.7×10381.4×10−45∼1.7×1038要狭窄很多因此在计算过程中很容易出现上溢出Overflowg65504g65504和下溢出Underflowg6×10−8g6×10−8的错误溢出之后就会出现“Nan”的问题。 在深度学习中由于激活函数的的梯度往往要比权重梯度小更易出现下溢出的情况。 舍入误差Rounding Error 舍入误差指的是当梯度过小小于当前区间内的最小间隔时该次梯度更新可能会失败用一张图清晰地表示 4. 解决问题的办法混合精度训练动态损失放大
混合精度训练Mixed Precision 混合精度训练的精髓在于“在内存中用FP16做储存和乘法从而加速计算用FP32做累加避免舍入误差”。混合精度训练的策略有效地缓解了舍入误差的问题。损失放大Loss Scaling 即使用了混合精度训练还是会存在无法收敛的情况原因是激活梯度的值太小造成了下溢出Underflow。损失放大的思路是 反向传播前将损失变化dLoss手动增大2k2k倍因此反向传播时得到的中间变量激活函数梯度则不会溢出反向传播后将权重梯度缩2k2k倍恢复正常值。
Apex的新APIAutomatic Mixed Precision (AMP)
曾经的Apex混合精度训练的api仍然需要手动half模型已经输入的数据比较麻烦现在新的api只需要三行代码即可无痛使用
from apex import amp
model, optimizer amp.initialize(model, optimizer, opt_levelO1) # 这里是“欧一”不是“零一”
with amp.scale_loss(loss, optimizer) as scaled_loss:scaled_loss.backward()opt_level 其中只有一个opt_level需要用户自行配置 O0纯FP32训练可以作为accuracy的baselineO1混合精度训练推荐使用根据黑白名单自动决定使用FP16GEMM, 卷积还是FP32Softmax进行计算。O2“几乎FP16”混合精度训练不存在黑白名单除了Batch norm几乎都是用FP16计算。O3纯FP16训练很不稳定但是可以作为speed的baseline 动态损失放大Dynamic Loss Scaling AMP默认使用动态损失放大为了充分利用FP16的范围缓解舍入误差尽量使用最高的放大倍数224224如果产生了上溢出Overflow则跳过参数更新缩小放大倍数使其不溢出在一定步数后比如2000步会再尝试使用大的scale来充分利用FP16的范围 干货踩过的那些坑
这一部分是整篇博客最干货的部分是瓦砾在最近在apex使用中的踩过的所有的坑由于apex报错并不明显常常debug得让人很沮丧但只要注意到以下的点95%的情况都可以畅通无阻了
判断你的GPU是否支持FP16构拥有Tensor Core的GPU2080Ti、Titan、Tesla等不支持的Pascal系列就不建议折腾了。常数的范围为了保证计算不溢出首先要保证人为设定的常数包括调用的源码中的不溢出如各种epsilonINF等。Dimension最好是8的倍数Nvidia官方的文档的2.2条表示维度都是8的倍数的时候性能最好。要求维度是8的整数倍最重要的目的是为了能使用 Tensor CoreTensor Core 的算力是 CUDA Core 的好多倍。涉及到sum的操作要小心很容易溢出类似Softmax的操作建议用官方API并定义成layer写在模型初始化里。模型书写要规范自定义的Layer写在模型初始化函数里graph计算写在forward里。某些不常用的函数在使用前需要注册amp.register_float_function(torch, sigmoid)某些函数如einsum暂不支持FP16加速建议不要用的太heavyxlnet的实现改FP16困扰了我很久。需要操作模型参数的模块类似EMA要使用AMP封装后的model。需要操作梯度的模块必须在optimizer的step里不然AMP不能判断grad是否为Nan。欢迎补充。。。
总结
这篇从理论到实践地介绍了混合精度计算以及Apex新APIAMP的使用方法。瓦砾现在在做深度学习模型的时候几乎都会第一时间把代码改成混合精度训练的了速度快精度还不减确实是调参炼丹必备神器。目前网上还并没有看到关于AMP以及使用时会遇到的坑的中文博客所以这一篇也是希望大家在使用的时候可以少花一点时间debug。当然如果读者们有发现新的坑欢迎交流我会补充在博客中。
Reference
Intel的低精度表示用于深度学习训练与推断Nvidia官方的混合精度训练文档Apex官方使用文档[Nvidia-Training Neural Networks with Mixed Precision](http://on-demand.gputechconf.com/gtc-taiwan/2018/pdf/5-1_Internal Speaker_Michael Carilli_PDF For Sharing.pdf)