转载https://blog.csdn.net/yingwei13mei/article/details/89301953
手推RA https://blog.csdn.net/dpppBR/article/details/80445569

深度学习的高性能计算技术

介绍

在过去几年中,神经网络已被证明是解决各种问题的极其有效的工具,并且在规模和计算要求方面迅速增长。 2012年,用于图像识别的超级卷积网络在物体识别方面取得了巨大进步,花了一周时间用两个GPU,拥有6000万个参数。 2016年,研究人员在语言建模方面取得了突破,该网络拥有超过10亿个参数,在32个GPU上训练了三个星期。在百度研究所的硅谷AI实验室内,2014年我们的深度语音识别系统的第一次迭代大约有1100万个参数,而一年后的下一次迭代已经增长到1亿个参数。

随着神经网络的参数数量和计算需求的增长,在许多节点和许多GPU上高效并行化神经网络训练变得越来越重要,因为等待数月的大型网络训练会减慢实验速度并限制进一步的发展。在这篇文章中,我们介绍了一种来自高性能计算(HPC)领域的技术,并演示了如何将其应用于深度学习以在神经网络训练中实现显着的性能提升。

通信问题

在将神经网络的训练并行化到许多GPU上时,您必须选择如何将不同的操作分配到可用的不同GPU上。在这里,我们专注于一种称为数据并行随机梯度下降(SGD)的技术。

模型并行技术不同,模型并行指的是将模型部署到很多设备上(设备可能分布在不同机器上,下同)运行,比如多个机器的GPUs。当神经网络模型很大时,由于显存限制,它是难以在跑在单个GPU上,这个时候就需要模型并行。比如Google的神经机器翻译系统,其可能采用深度LSTM模型,如下图所示,此时模型的不同部分需要分散到许多设备上进行并行训练。深度学习模型一般包含很多层,如果要采用模型并行策略,一般需要将不同的层运行在不同的设备上,但是实际上层与层之间的运行是存在约束的:前向运算时,后面的层需要等待前面层的输出作为输入,而在反向传播时,前面的层又要受限于后面层的计算结果。所以除非模型本身很大,一般不会采用模型并行,因为模型层与层之间存在串行逻辑。但是如果模型本身存在一些可以并行的单元,那么也是可以利用模型并行来提升训练速度,比如GoogLeNet的Inception模块。

在数据并行方式中与标准SGD一样,梯度下降是通过数据子集(小批量)完成的,需要多次迭代才能在整个数据集中进行。然而,在数据并行训练中,每个GPU具有整个神经网络模型的完整副本,并且对于每次迭代,仅分配小批量中的样本的子集。对于每次迭代,每个GPU在其数据上运行网络的前向传播,然后进行反向误差传播以计算相对于网络参数的丢失梯度。最后,GPU彼此通信获取由不同GPU计算出的梯度的平均,将平均梯度应用于权重以获得新的权重。 GPU都在锁定步骤中进行迭代,并且一旦GPU完成其迭代,它必须等待其他所有GPU完成它们自己的迭代以便可以正确地更新权重。这相当于在单个GPU上执行SGD,但我们通过在多个GPU之间分配数据并行执行计算来获得加速。

当您只有两个GPU和以兆字节数据为单位的参数时,这些GPU的通信方式可能无关紧要。 但是,当您的模型具有数十亿个参数时,梯度可能占用千兆字节的空间(因为每个参数都有一个梯度值),并且您正在协调数十个GPU,通信机制变得至关重要。

例如,考虑最直接的通信机制。 每个GPU都在其小批量的子集上计算梯度。 然后,每个GPU将其梯度发送到单个GPU,该GPU获取所有梯度的平均值,并将平均值发送回所有其他GPU。

需要发送的数据越多,发送数据的时间就越长;每个通信信道都具有最大吞吐量(带宽)限制。例如,良好的互联网连接可以提供每秒15兆字节的带宽,而千兆以太网连接可以提供每秒125兆字节的带宽。 HPC群集上的专用网络硬件(如Infiniband)可在节点之间提供每秒几千兆字节的带宽。

在从单个GPU发送和接收数据的直连机制中,该单个GPU必须从所有GPU接收所有参数,并将所有参数发送到所有GPU。系统中的GPU越多,通信成本就越高。

让我们评估一下这种通信策略如何在真实模型上运行,例如以百度深度语音2为模型的语音识别网络,具有三亿个可训练参数。每个参数四个字节的三亿个参数大约是1.2千兆字节的数据。假设您系统上的网络硬件可以支持每秒1千兆字节的带宽;在这种情况下,如上所述将系统并行化到两个GPU上将使每次迭代减慢1.2秒。将您的训练任务并行化到10个GPU将使每次迭代减慢10.8秒;随着GPU数量的增长,每次迭代所需的时间呈线性增长。即使每次迭代花费几秒钟,通信成本的这种线性增长也会使得进一步的并行化变得不切实际并且会降低训练效率。

一种替代方案是放弃训练算法的同步性质,并通过梯度下降的迭代消除所有GPU在锁定步骤中前进的约束。但是,虽然这可以使您的模型更容易并行化,删除此约束的算法(异步SGD的变量)却可能难以调试,并且对于某些模型可以收敛到部分子结果,这不是我们这篇文章的目的。

相反,我们可以通过使用高性能计算领域的分布式reduction算法来解决通信问题,并充分利用带宽最优的ring-allreduce方案。

The Ring Allreduce

上述简化通信策略的主要问题是通信成本随着系统中GPU的数量线性增长。 相反,ring allreduce是一种算法,其通信成本是恒定的并且与系统中GPU的数量无关,并且仅由系统中GPU之间的最慢连接确定; 事实上,如果你只考虑带宽作为通信成本的一个因素(并忽略延迟),那么ring allreduce是一种最佳的通信算法。 (当您的模型很大时,这是对通信成本的一个很好的预估,并且您只需要较少数次数发送大量数据。)

Ring allreduce中的GPU排列在一个逻辑环中。 每个GPU应该有一个左邻居和一个右邻居; 它只会向其右邻居发送数据,并从其左邻居接收数据。

该算法分两步进行:第一步是scatter-reduce,然后是all-gather。 在scatter-reduce步骤中,GPU将交换数据,使得每个GPU最终得到最终结果的一部分。 在all-gather步骤中,GPU将交换这些块,以便所有GPU最终得到完整的最终结果。

The Scatter-Reduce

为简单起见,让我们假设目标是元素层面的,即浮点数的单个大数组的所有元素的总和; 系统中有N个GPU,每个GPU都有一个相同大小的数组,并且在allreduce的末尾,每个GPU都应该有一个相同大小的数组,其中包含原始数组中数字的总和。

首先,GPU将数组分成N个较小的块(其中N是环中的GPU数量)。


将数组分区为N个块

接下来,GPU将进行N-1次迭代的scatter-reduce; 在每次迭代中,GPU都会将其中一个块发送到其右邻居,并从其左邻居接收一个块并累积到该块中。 每次迭代发送和接收的块都是不同的; 第n个GPU通过发送块n和接收块n-1开始,然后从那里向后进行,每次迭代发送它在前一次迭代中接收到的块。

例如,在第一次迭代中,上图中的五个GPU将发送和接收以下块:

GPU Send Receive
0 Chunk0 Chunk4
1 Chunk1 Chunk0
2 Chunk2 Chunk1
3 Chunk3 Chunk2
3 Chunk4 Chunk3


在scatter-reduce第一次迭代过程中的数据传输

在第一次发送和接收完成后,每个GPU将具有一个块,该块由两个不同GPU上的相同块的总和组成。 例如,第二个GPU上的第一组块将是来自第二GPU和第一GPU的该组块中的值的总和。


在scatter-reduce第一次迭代完成以后立刻求和

在接下来的迭代中,该过程继续,并且最后,每个GPU将具有一个块,该块包含所有GPU中该块中的所有值的总和。 下面的图像演示了所有数据传输和中间结果,从第一次迭代开始,一直持续到scatter-reduce完成。

Scatter-reduce data transfers (iteration 1)

Scatter-reduce data transfers (iteration 2)

Scatter-reduce data transfers (iteration 3)


Scatter-reduce data transfers (iteration 4)


Final state after all scatter-reduce transfers

The Allgather

Scatter-reduce步骤完成后,每个GPU都是一个有值的数组,其中一些值(每个GPU一个块)是最终值,包括来自所有GPU的贡献。 为了完成allreduce,GPU必须交换这些块,以便所有GPU都具有所有必需的值。

Ring allgather与scatter-reduce相同(发送和接收的N-1次迭代),除了不是累积GPU接收的值以外,它们只是覆盖块。 第n个GPU首先发送第n + 1个块并接收第n个块,然后在将来的迭代中总是发送它刚收到的块。

例如,在我们的5-GPU设置建立的第一次迭代中,GPU将发送和接收以下块:

GPU Send Receive
0 Chunk1 Chunk0
1 Chunk2 Chunk1
2 Chunk3 Chunk2
3 Chunk4 Chunk3
3 Chunk0 Chunk4


Data transfers in the first iteration of the allgather

第一次迭代完成后,每个GPU将有两个最终数组的块。在接下来的迭代中,该过程继续,并且到最后,每个GPU将具有整个数组的完全累积值。

下面的图像演示了所有数据传输和中间结果,从第一次迭代开始直到全部收集完成。


Allgather data transfers (iteration 1)


Allgather data transfers (iteration 2)

Allgather data transfers (iteration 3)


Allgather data transfers (iteration 4)

Final state after all allgather transfers

Allreduce Communication Cost

回想一下,对于介绍中描述的简单通信算法,通信成本随着GPU的数量线性增长。 allreduce运行良好的主要原因是不再是这种情况。

在我们描述的系统中,N个GPU中的每一个将为scatter-reduce发送和接收N-1次值,为allgather发送和接收N-1次。每次,GPU将发送K / N值,其中K是在不同GPU上求和的数组中的值的总数。因此,传输到每个GPU的数据总量是

DataTransferred=2(N−1)KNDataTransferred=2(N−1)KNData Transferred=2(N−1)KNData Transferred=2(N−1)KNData Transferred=2(N−1)KN \text{Data Transferred} = 2(N-1)\dfrac {K} {N}Data Transferred=2(N−1)KNData Transferred=2(N−1)KNData Transferred=2(N−1)NK​6.0 gigabytes per second2.4 gigabytes​≈400 milliseconds per iteration

由于网络较深的层首先具有可用的梯度,我们可以在整个反向传播通道完成之前开始进行数据传输,因此真正的开销可能小于400毫秒; 通信和计算之间的重叠可以根据被优化的神经网络的性质而变化。

我们实现了上述语言模型,并测试了每次迭代所花费的时间,因为我们从单个GPU(没有通信开销)扩展到40个GPU。 这40个GPU排列成5个节点,每个节点有8个GPU,由Infiniband连接。 我们运行语言模型进行了300次迭代,batch size大小为32,并计算每秒处理的样本数。

使用3亿参数语言模型每秒处理的样本数量与同时进行同步训练的GPU数量呈线性关系。

如您所见,整个系统的吞吐量与GPU的数量呈线性关系; 超过某个点时,添加更多GPU不会导致每次迭代速率显著减慢。 在40个GPU上运行模型每次迭代大约需要650-700毫秒,而在单个GPU上大约需要370毫秒。 由于通过我们的估计,通信将花费400毫秒,我们通过将反向传播与数据传输重叠来每次迭代额外节省70-120毫秒。

结论

Ring allreduce是一种来自高性能计算领域的技术,它允许我们在许多设备和许多节点上有效地平均化神经网络中的梯度。通过在训练期间使用这种带宽优化算法,您可以大幅减少通信开销并扩展到更多设备,同时仍保留同步随机梯度下降的确定性和可预测的收敛特性。该算法是网络架构和深度学习框架无关的,可以为数据并行训练的效率提供切实和直接的好处,同时也是相当简单和易于实现的。

为了让您更容易利用这些技术,今天我们发布了baidu-allreduce,一个C程序库,演示了可以嵌入到任何支持MPI的应用程序中的allreduce算法。此外,优步的优秀Horovod库实现了我们在这里提到的技术。

我们希望其他深度学习框架能够在适当的情况下利用类似的技术,并且使用这些工具,您将能够轻松高效地将神经网络模型扩展到许多机器,而不受您选择的框架的影响。

参考

1.Krizhevsky, Alex, Ilya Sutskever, and Geoffrey E. Hinton. “ImageNet classification with deep convolutional neural networks.” Advances in neural information processing systems. 2012.

2.Jozefowicz, Rafal, et al. “Exploring the limits of language modeling.” arXiv preprint arXiv:1602.02410 (2016).

3.Amodei, Dario, et al. “Deep speech 2: End-to-end speech recognition in english and mandarin.” arXiv preprint arXiv:1512.02595 (2015).

4.Patarasuk, Pitch, and Xin Yuan. “Bandwidth optimal all-reduce algorithms for clusters of workstations.” Journal of Parallel and Distributed Computing 69.2 (2009): 117-124.

5.Hannun, Awni, et al. “Deep speech: Scaling up end-to-end speech recognition.” arXiv preprint arXiv:1412.5567 (2014).

参考:http://andrew.gibiansky.com/blog/machine-learning/baidu-allreduce/

【分布式训练-Ring AllReduce】相关推荐

  1. 美国南加州大学骆沁毅:构建高性能的异构分布式训练算法

    计算机体系结构领域国际顶级会议每次往往仅录用几十篇论文,录用率在20%左右,难度极大.国内学者在顶会上开始发表论文,是最近十几年的事情. ASPLOS与HPCA是计算机体系结构领域的旗舰会议.其中AS ...

  2. 带你认识大模型训练关键算法:分布式训练Allreduce算法

    摘要:现在的模型以及其参数愈加复杂,仅仅一两张的卡已经无法满足现如今训练规模的要求,分布式训练应运而生. 本文分享自华为云社区<分布式训练Allreduce算法>,原文作者:我抽签必中. ...

  3. Tensorflow框架是如何支持分布式训练的?

    参加 2019 Python开发者日,请扫码咨询 ↑↑↑ 作者 | 杨旭东 转载自知乎<算法工程师的自我修养>专栏 Methods that scale with computation ...

  4. tensowflow 训练 远程提交_一文说清楚Tensorflow分布式训练必备知识

    Note: 原文发表于我的知乎专栏:算法工程师的自我修养,欢迎关注! Methods that scale with computation are the future of AI. -Rich S ...

  5. [分布式训练] 单机多卡的正确打开方式:理论基础

    [分布式训练] 单机多卡的正确打开方式:理论基础 转自:https://fyubang.com/2019/07/08/distributed-training/ 瓦砾由于最近bert-large用的比 ...

  6. ztree局部刷新节点_神经网络训练的世界记录是怎样被刷新的 -- 总结分布式训练的计算场景...

    还是在今年(2018年)11月美国感恩节放假期间,我无意点开我的新论文搜索关注,假期的懈怠顿时被一扫而空.一篇谷歌的新论文跳入眼帘,声称打破了几天前刚建立的分布式训练速度的记录.各大公司训练速度记录上 ...

  7. 全网最全-超大模型+分布式训练架构和经典论文

    如何利用计算中心成千上百的AI加速芯片的集群,训练参数量超过百亿的大规模模型?并行计算是一种行之有效的方法,除了分布式并行计算相关的技术之外,其实在训练大模型的过程还会融合更多的技术,如新的算法模型架 ...

  8. 南加州大学钱学海:去中心化分布式训练系统的最新突破

    2020 北京智源大会 本文属于2020北京智源大会嘉宾演讲的整理报道系列.北京智源大会是北京智源人工智能研究院主办的年度国际性人工智能高端学术交流活动,以国际性.权威性.专业性和前瞻性的" ...

  9. [翻译] 使用 TensorFlow 进行分布式训练

    [翻译] 使用 TensorFlow 进行分布式训练 文章目录 [翻译] 使用 TensorFlow 进行分布式训练 0x00 摘要 1. 概述 2. 策略类型 2.1 MirroredStrateg ...

最新文章

  1. 用css3简单实现进度条
  2. 压缩目录Linux常用的几种文件压缩解压方法
  3. Android利用ViewPager实现滑动广告板
  4. 实例入手Vue-Route给引用组件传值以及实现组件重用
  5. 【技术累积】【点】【java】【27】@JSONField
  6. 用 Python 实现溺水识别
  7. C++ 空间配置器(allocator)
  8. 6、mysql与suse查看版本信息
  9. Oracle增加临时表空间
  10. 毫米和像素怎么换算_像素和厘米怎么换算?
  11. java判断邮箱格式
  12. 1.CPU体系架构-RISC指令集和CISC指令集
  13. “蚂蚁牙黑,蚂蚁呀吼”一夜间火遍全网?别忽略了潜在风险
  14. 关于桌面程序被安全软件误判为HEUR:Trojan.Win32.Generic的解决方案
  15. Bootstrap导航栏下拉菜单不生效的问题
  16. 用matlab对图像进行边缘填充,matlab中的图像边界填充函数 | 学步园
  17. Navicat连接Linux的MySQL出错排查
  18. Android 开发环境下载地址
  19. 【Unity主程手记学习】第一章——软件架构
  20. 卷积积分结合律性质的证明

热门文章

  1. 那些清华北大随便挑的高考状元们,后来都过上了怎样的生活?
  2. 论文中world自带公式编辑器编辑的公式每次打开公式自动加粗问题解决。
  3. linux编译符号那些事儿
  4. 文字图片水平居中对齐
  5. 职场情商训练 - 下属的工作技巧
  6. 仿潮自拍个人中心拖拉效果
  7. DOTA2攻速计算公式研究
  8. Ubuntu Edgy Sources list
  9. SQL中的笛卡尔你真的懂吗?
  10. (持续更新)Ubuntu22.04双系统的安装、扩容、重装及配置