持续创作,加快生长!这是我参与「日新方案 10 月更文应战」的第21天,点击查看活动概况
导读
只需求增加几行代码,就能够得到更快速,更省显存的PyTorch模型。

你知道吗,在1986年Geoffrey Hinton就在Nature论文中给出了反向传达算法?
此外,卷积网络最早是由Yann le cun在1998年提出的,用于数字分类,他运用了一个卷积层。可是直到2012年晚些时候,Alexnet才通过运用多个卷积层来完成最先进的imagenet。
那么,是什么让他们现在如此出名,而不是之前呢?
只有在咱们拥有很多核算资源的情况下,咱们才能够在最近的曩昔试验和充分运用深度学习的潜力。
可是,咱们是否已经足够好地运用了咱们的核算资源呢?咱们能做得更好吗?
这篇文章的主要内容是关于怎么运用Tensor Cores和主动混合精度更快地练习深度学习网络。
什么是Tensor Cores?
依据NVIDIA的网站:
NVIDIA Turing和Volta GPUs都是由Tensor Cores驱动的,这是一项革命性的技术,提供了突破性的AI性能。Tensor Cores能够加快AI中心的大矩阵运算,在一次运算中就能够完成混合精度的矩阵乘法和累加运算。在一个NVIDIA GPU上有数百个Tensor Cores并行运转,这大大提高了吞吐量和效率。
简略地说,它们是专门的cores,非常合适特定类型的矩阵操作。

咱们能够将两个FP16矩阵相乘,并将其增加到一个FP16/FP32矩阵中,从而得到一个FP16/FP32矩阵。Tensor cores支持混合精度数学,即以半精度(FP16)进行输入,以全精度(FP32)进行输出。上述类型的操作对许多深度学习任务具有内涵价值,而Tensor cores为这种操作提供了专门的硬件。
现在,运用FP16和FP32主要有两个好处。
- FP16需求更少的内存,因而更简单练习和部署大型神经网络。它还只需求较少的数据移动。
- 数学运算在下降精度的Tensor cores运转得更快。NVIDIA给出的Volta GPU的切当数字是:FP16的125 TFlops vs FP32的15.7 TFlops(8倍加快)。
但也有缺点。当咱们从FP32转到FP16时,咱们需求下降精度。

FP32 vs FP16: FP32 有8个指数位和23个分数位,而FP16有5个指数位和10个分数位。
可是FP32真的有必要吗?
实际上,FP16能够很好地表明大多数权重和梯度。所以存储和运用FP32是很浪费的。
那么,咱们怎么运用Tensor Cores?
我查看了一下我的Titan RTX GPU有576个tensor cores和4608个NVIDIA CUDA中心。可是我怎么运用这些tensor cores呢?
坦白地说,NVIDIA用几行代码就能提供主动混合精度,因而运用tensor cores很简略。咱们需求在代码中做两件事:
- 需求用到FP32的运算比如Softmax之类的就分配用FP32,而Conv之类的操作能够用FP16的则被主动分配用FP16。

- 运用丢失缩放为了保存小的梯度值。梯度值可能落在FP16的范围之外。在这种情况下,梯度值被缩放,使它们落在FP16范围内。

假如你还不了解布景细节也不要紧,代码完成相对简略。
运用PyTorch进行混合精度练习:
让咱们从PyTorch中的一个基本网络开端。
N,D_in,D_out=64,1024,512
x=torch.randn(N,D_in,device="cuda")
y=torch.randn(N,D_out,device="cuda")
model=torch.nn.Linear(D_in,D_out).cuda()
optimizer=torch.optim.SGD(model.parameters(),lr=1e-3)
fortoinrange(500):
y_pred=model(x)
loss=torch.nn.functional.mse_loss(y_pred,y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
为了充分运用主动混合精度练习的优势,咱们首先需求装置apex库。只需在终端中运转以下指令。
$gitclonehttps://github.com/NVIDIA/apex
$cdapex
$pipinstall-v--no-cache-dir--global-option="--cpp_ext"--global-option="--cuda_ext"./
然后,咱们只需向神经网络代码中增加几行代码,就能够运用主动混合精度(AMP)。
fromapeximportamp
N,D_in,D_out=64,1024,512
x=torch.randn(N,D_in,device="cuda")
y=torch.randn(N,D_out,device="cuda")
model=torch.nn.Linear(D_in,D_out).cuda()
optimizer=torch.optim.SGD(model.parameters(),lr=1e-3)
model,optimizer=amp.initialize(model,optimizer,opt_level="O1")
fortoinrange(500):
y_pred=model(x)
loss=torch.nn.functional.mse_loss(y_pred,y)
optimizer.zero_grad()
withamp.scale_loss(loss,optimizer)asscaled_loss:
scaled_loss.backward()
optimizer.step()
在这里你能够看到咱们用amp.initialize
初始化了咱们的模型。咱们还运用amp.scale_loss
来指定丢失缩放。
基准测试
咱们能够通过运用这个git仓库:github.com/znxlwm/pyto…
gitclonehttps://github.com/MLWhiz/data_science_blogs
cddata_science_blogs/amp/pytorch-apex-experiment/
pythonrun_benchmark.py
pythonmake_plot.py--GPU'RTX'--method'FP32''FP16''amp'--batch12825651210242048
这会在home目录中生成下面的图:

在这里,我运用不同的精度和批巨细设置练习了同一个模型的多个实例。咱们能够看到,从FP32到amp,内存需求削减,而精度保持大致相同。时间也会削减,但不会削减那么多。这可能是因为数据集或模型太简略。
依据NVIDIA给出的基准测试,AMP比规范的FP32快3倍左右,如下图所示。

在单精度和主动混合精度两种精度下,加快比为固定周期练习的时间比。
英文原文:towardsdatascience.com/faster-and-…