一行代码让性能提升2倍

作者: 佚名 2020-03-13 13:23:42

 随着生活节奏的加快,「等待」已经越来越成为人们希望远离的事情。但是在深度学习领域,模型的参数、数据集的规模等等动辄就是以亿为单位,甚至更大,因此当模型训练成功之时,放一首张靓颖的「终于等到你」作为背景音乐实在是太应景了。

那如果现在向你推荐一款神器,可以实现训练速度翻倍,访存效率翻倍,你心动吗?心动不如行动(这可不是电视直销,别着急换频道),来和我一起看看这款神器——基于PaddlePaddle核心框架的自动混合精度(Automatic Mixed Precision) 技术,简称飞桨 AMP 技术。

飞桨 AMP 技术仅仅通过一行代码即可帮助用户简便快速的将单精度训练的模型修改为自动混合精度训练。同时通过黑白名单和动态 Loss Scaling 来保证训练的稳定性,避免出现 INF 或者 NAN 问题。PaddlePaddle AMP 可以充分发挥新一代 NVIDIA GPU 中 Tensor Core 的计算性能优势,ResNet50、Transformer 等模型的训练速度与单精度训练相比可以提升到 1.5~2.9 倍。

那么它是怎么实现的呢?我们先从什么是自动混合精度技术讲起。

什么是自动混合精度技术

顾名思义,自动混合精度是一种自动将半精度和单精度混合使用,从而加速模型训练的技术。其中单精度(Float Precision32,FP32)好理解,是计算机常用的一种数据类型。那么半精度是什么呢?如图 1 所示,半精度(Float Precision16,FP16)是一种相对较新的浮点类型,在计算机中使用 2 字节(16 位)存储,在 IEEE 754-2008 中,它被称作 binary16。与计算中常用的单精度和双精度类型相比,Float16 更适于在精度要求不高的场景中使用。

不言而喻,在深度学习领域,如果使用 Float16 代替 Float32 来存储数据,那么开发者就可以训练更大更复杂的模型,使用更大的 batch size。因此对于那些恨不得挖掘出 GPU 里每一个晶体管全部潜力的科学家们怎么能放过它呢?同时由于 NVIDIA 推出了具备 Tensor Core 技术的 Volta 及 Turing 架构 GPU,使半精度计算趋向成熟。在相同的 GPU 硬件上,Tensor Core 的半精度计算吞吐量是单精度的 8 倍。

但显而易见,使用 Float16 肯定会同时带来计算精度上的损失。但对深度学习训练而言,并不是所有计算都要求很高的精度,一些局部的精度损失对最终训练效果影响很微弱,仅需要某些特殊步骤保留 Float32 的计算精度即可。因此混合精度计算的需求应运而生。我们可以将训练过程中一些对精度损失不敏感且能使用 Tensor Core 进行加速的运算使用半精度处理,最大限度的提升访存和计算效率。

但是对每个具体模型,人工去设计和尝试精度混合的方法,是非常繁琐的,我们迫切需要一种更简洁的方式,高效地实现混合精度的训练。AMP,顾名思义,就是让混合精度训练自动化,因此使用简单是它的重要特色。具体咋用,咱们往下看!

AMP 的使用方法

下面以 MNIST 为例介绍如何使用飞桨 AMP 技术。MNIST 网络定义的代码如下所示。其中 conv2d、batch_norm(bn)和 pool2d 的数据布局需要提前设置为'NHWC',这样有利于加速混合精度训练,并且 conv2d 的输出通道数需要设置为 4 的倍数,以便使用 Tensor Core 技术加速。

  1. import paddle.fluid as fluid  
  2. def MNIST(data, class_dim):  
  3.     conv1 = fluid.layers.conv2d(data, 16, 5, 1, act=Nonedata_format='NHWC' 
  4.     bn1 = fluid.layers.batch_norm(conv1, act='relu'data_layout='NHWC')   
  5.     pool1 = fluid.layers.pool2d(bn1, 2, 'max', 2, data_format='NHWC')   
  6.     conv2 = fluid.layers.conv2d(pool1, 64, 5, 1, act=Nonedata_format='NHWC' 
  7.     bn2 = fluid.layers.batch_norm(conv2, act='relu'data_layout='NHWC')   
  8.     pool2 = fluid.layers.pool2d(bn2, 2, 'max', 2, data_format='NHWC')   
  9.     fc1 = fluid.layers.fc(pool2, size=50act='relu')   
  10.     fc2 = fluid.layers.fc(fc1, size=class_dimact='softmax' 
  11.     return fc2 

为了训练 MNIST 网络,还需要定义损失函数来更新权重参数,此处使用的优化损失函数是 SGDOptimizer。为了简化说明,这里省略了迭代训练的相关代码,仅体现损失函数及优化器定义相关的内容。

  1. import paddle.fluid as fluid  
  2. import numpy as np  
  3. data = fluid.layers.data(   
  4.     name='image'shape=[None, 28, 28, 1], dtype='float32' 
  5. label = fluid.layers.data(name='label'shape=[None, 1], dtype='int64' 
  6. out = MNIST(data, class_dim=10 
  7. loss = fluid.layers.cross_entropy(input=outlabellabel=label)  
  8. avg_loss = fluid.layers.mean(loss)  
  9. sgd = fluid.optimizer.SGDOptimizer(learning_rate=1e-3)  
  10. sgd.minimize(avg_loss) 

那么如何将上面的示例改造成使用 AMP 训练的方式呢?用户仅需要使用飞桨提供的 AMP 函数 fluid.contrib.mixed_precision.decorate 将原来的优化器 SGDOptimizer 进行封装,然后使用封装后的优化器(mp_sgd)更新参数梯度,代码如下所示:

  1. sgd = fluid.optimizer.SGDOptimizer(learning_rate=1e-3)  
  2. mp_sgd = fluid.contrib.mixed_precision.decorator.decorate(sgd)  
  3. mp_sgd.minimize(avg_loss) 

如上即为最简单的飞桨 AMP 功能使用方法。

但是大家可能有些疑问,模型是如何感知哪些算子(Op)需要被转换呢?是不是还需要手工指定呢?算子那么多,我怎么知道哪个算子可以被转换呢?别着急,PaddlePaddle已经帮你定制好了,这也是这门技术被称为「自动」的原因之一,且请往下看!

黑白名单功能

为了让开发者可以方便快捷的使用混合精度计算,PaddlePaddle的工程师们使用了大量模型在不同应用场景中反复验证,然后根据半精度数据类型计算的稳定性和加速效果,梳理出一系列适合转换为半精度计算的算子,并将这些算子定义到了一份白名单文件中。同时对于一些经过验证发现不适合转换的算子,也就是使用半精度计算会导致数值不精确的算子将被记录到黑名单文件中。此外一些对半精度计算没有多少影响的算子归类于灰名单。在使用 AMP 训练过程中,系统会自动读取黑白名单,从而感知到哪些算子需要被转换为半精度计算。

对于某些特殊场景,如果开发者希望使用自定义的黑白名单,则可以使用 AutoMixedPrecisionLists 类设置,代码示例如下所示。

  1. sgd = SGDOptimizer(learning_rate=1e-3)  
  2. # 指定自定义的黑白名单,其中 list1 和 list2 为包含有算子名称的列表  
  3. amp_list = AutoMixedPrecisionLists(custom_white_list=list1,custom_black_list=list2 
  4. mp_sgd = fluid.contrib.mixed_precision.decorator.decorate(sgd, amp_list)  
  5. mp_sgd.minimize(avg_loss) 

那么自动混合精度技术被称为「自动」的原因之二呢?那就是下面的自动调整 Loss Scaling 功能。

自动调整 Loss Scaling

AMP 技术在提升访存和计算效率的同时,伴随的副作用也是很明显的。那就是由于半精度数据类型的精度范围与转换前的单精度相比过窄,导致容易产生 INF 和 NAN 问题。为了避免此类问题,AMP 技术实现了自动调整 Loss Scaling 功能,即在 AMP 训练过程中,为了避免精度下溢,每训练一定数量批次的数据,就将 Loss 放大指定倍数。如果 Loss 在放大过程中发生上溢,则可以再缩小一定倍数,确保整个训练过程中,梯度可以正常收敛。

fluid.contrib.mixed_precision.decorate 函数携带了自动调整 Loss Scaling 功能相关的参数,这些参数都带有默认值,如下面代码所示。这些默认值都是经过飞桨工程师多次验证后定义的。通常情况下,用户可以直接使用,无需重新设置。

  1. sgd = SGDOptimizer(learning_rate=1e-3)  
  2. mp_sgd = fluid.contrib.mixed_precision.decorator.decorate(sgd,   
  3.             init_loss_scaling=2**15,   
  4.             incr_every_n_steps=2000,   
  5.             use_dynamic_loss_scaling=True 
  6. mp_sgd.minimize(avg_loss) 

多卡 GPU 训练的优化

在新发布的PaddlePaddle核心框架 1.7 版本上,AMP 技术深度优化了多卡 GPU 训练。如图 2 所示,在优化之前的参数梯度更新过程中,梯度计算时虽然使用的是半精度数据类型,但是不同 GPU 卡之间的梯度传输数据类型仍为单精度。

为了降低 GPU 多卡之间的梯度传输带宽,我们将梯度传输这个过程提到 Cast 操作之前,而每个 GPU 卡在得到对应的半精度梯度后再执行 Cast 操作,将其转变为单精度类型,如图 3 所示。这一优化在训练网络复杂度较大的模型时,对减少带宽占用方面非常有效,如多卡训练 BERT-Large 模型。

训练性能对比(AMP VS FP32)

飞桨 AMP 技术在 ResNet50、Transformer 等模型上训练速度相对于 FP32 训练来说有非常大的优势,下面以 ResNet50 模型为例,从下图中可以看出,ResNet50 的 AMP 训练相对与 FP32 训练,单卡加速比可达 2.9 倍,八卡加速比可达 2.8 倍。

代码 人工智能 深度学习
上一篇:聊天机器人的体系结构模型及响应生成机制是怎样的? 下一篇:机器学习工程师和数据科学家之间的区别
评论
取消
暂无评论,快去成为第一个评论的人吧

更多资讯推荐

人工智能辅助下社交媒体营销人员的十大戒律

如果我告诉你,在社交媒体中使用人工智能工具(并正确地使用)能够增强每名用户的消费者旅程,从而留下更多的用户,且留存时间更长,会怎么样呢?

读芯术 ·  1天前
2020~2030:人工智能将占据主导地位的十年

AntWorks预测,在未来十年中,很难找到一个没有利用AI来智能地自动化业务流程的行业。在所有行业中都有无数的AI用例,这是我们对2020年及以后的预测。

CDA数据分析师 ·  1天前
AI人工智能在2020年的7个发展趋势

随着对其他AI应用程序需求的增长,企业将需要投资有助于其加快数据科学流程的技术。然而:实施和优化机器学习模型只是数据科学挑战的一部分。

CDA数据分析师 ·  3天前
物联网和机器人如何协同工作

很显然,机器人和物联网是两个完全不同的领域。但是,毫无疑问,它们正在协同工作,因为彼此都在帮助对方发展和创新。

iothome ·  3天前
腾讯和清华发表新基建领域最新成果:数据中心电池设备AI诊断服务

近日,腾讯数据中心与清华大学自动化系智网中心团队的贾庆山老师合作论文被第21届IFAC国际自动控制世界大会录取。

佚名 ·  3天前
哈工大造出柔性机器人,人造肌肉能和象鼻一样灵活了!

近日,国际著名期刊 Soft Robotics 刊登了哈尔滨工业大学冷劲松教授团队与美国马里兰大学 Norman M. Wereley 教授团队的共同研究成果,题为 Novel Bending and Helical Extensile/Contractile Pneumatic Artificial Muscles Inspired by Elephant Trunk(受象鼻启发的新型弯曲螺旋可伸展/收缩气动人工肌肉)。

付静 ·  3天前
机器人警察正在将虚幻变成现实

配备了人工智能、计算机视觉、物联网和其他先进技术的机器人警察可以帮助维护法律和秩序,并确保社区安全。

iothome ·  4天前
宫崎骏动画里的新垣结衣见过没?这个开源动漫生成器让你的照片秒变手绘日漫

随手拍张照片,顺势转换为宫崎骏、新海诚等日漫大师的手绘风格作品,这个专门生成动漫图像的 GAN,实测很好用。

肖清、思 ·  4天前
Copyright©2005-2020 51CTO.COM 版权所有 未经许可 请勿转载