对神经网络加速Mixed-Precision的理解

NVIDIA对AMP的介绍

  1. 先把weight矩阵们转一份FP16的copy;
  2. 前向、后向计算,全部用FP16的(包括激活、W、激活的梯度、W的梯度);
  3. W的梯度,需要先从FP16转换为FP32,再更新总的FP32的W;为什么:如果总的W也使用FP16,则由于数值指数范围较小,加上同是FP16的gradients,误差较大(特别是gradients绝对值较小接近0时,就加不上了);
  4. Optional: 某些网络,需要把Loss扩大S倍,目的是把其激活的梯度扩大S倍,从而不至于其一部分数值太小变成0;如果用了该技术,则需要在最后W的梯度往总梯度上更新之前,把W的梯度再缩小S倍;

问:为了把激活的梯度扩大S倍,为什么通过把Loss扩大S倍来实现:

答:链式法则;L的x的导数,把公式写出来,可以发现要把这个导数扩大S倍,只需要把L对y的导数扩大S倍即可,等价于把L扩大S倍;

问:为什么只提到了把激活的梯度扩大S倍:

答:有些网络,不扩大S倍也行;有些网络,只有激活的梯度(W的梯度,W,激活,都没事),在FP16情况下会落到0;

问:为什么要把W的梯度,最后要缩小S倍:

答:同理,还是根据链式法则(也就是求导公式),如果L扩大了S倍,则W的梯度也就扩大了S倍,所以要最后缩小S倍,才能保证正确;(我认为,先转成FP32, 再缩小S倍,再更新,更精确些,不知道是不是这么实现的?

问:为什么快:

答:FP16利用了TensorCore;

效果:在收敛效果相近的前提下,可以1. 加快计算速度;2.减少memory占用(从而enable更大的minibatch、更大的model);3.加快显存访问、主存offload速度;

NVIDIA自吹的是平均训练速度达到3X;Pytorch报道的是2X;

另:

AMP支持已经进入Pytorch核心代码了:torch.cuda.amp

细节

如果要做gradient的norm或者cliping,需要手动先unscale,再执行GradScaler的step更新;

如果使用gradient-accumulation技术(即用多次小batch来模拟一个大batch),每次backward之后,scaled梯度会自动累加起来,最后调用GradScaler的step(自动unscaler)以及optimizer的zero_grad;

手动在Loss中加入W的正则项时,如果使用AMP技术,则要特殊处理一下(即把W先unscale,再在autocast区域里计算正则项并加入到Loss(我估计在autocast里,会先把W进行scale,再计算)),很Ugly...

浮点数原理:

符号位,指数位,尾数位;

指数位的全0和全1是表示0和NaN这种特殊数据用的;

位数位放在小数点后面,小数点前面隐含是1;

例如+1.10110*(2^(8-127))); 其中8是指数位的东西;127是定死的“指数偏移”(我的理解是,这样指数位就不需要使用补码表示了);其中10110是尾数位的东西;

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值