技术博客神经网络分布式训练中参数优先流传办法
作者:倪昊
这篇论文来自 2019 年 SysML 会议中 Parallel & Distributed Learning 的局部。
数据并行训练(Data parallel training)曾经宽泛地使用在在深度神经网络的分布式计算中,然而,分布式计算带来的性能晋升常常受限于参数同步性能的瓶颈。作者等人提出了一种新的参数同步机制:Priority-based Parameter Propagation(P3),进步了模型的训练集群对网络带宽的利用率,放慢了模型的训练速度。
咱们首先来回顾一下神经网络的分布式训练。
深度神经网络(DNN)的分布式训练
神经网络的分布式训练通常有两种策略。一种是模型并行,指的是分布式系统中的不同机器别离负责在单个网络的不同局部计算,即把模型的不同层(layer)放到不同的工作节点上,罕用与模型过大的状况,它的计算效率不高。另一种是数据并行,不同的机器有着整个模型的齐全拷贝,每个机器只取得整个数据的不同局部,即把训练数据分成许多块,分给不同的 worker 节点,各个节点独自进行计算,然而共享一个模型,计算的后果通过某些办法联合起来。当然,这两种策略并不抵触,齐全能够混合应用。
数据并行罕用的架构是参数服务器(Parameter Server),即 PS 架构。
数据并行有两种不同的并行模式:同步训练和异步训练。同步训练是指所有 worker 节点的梯度都计算实现,对立进行梯度更新。而异步训练是指 worker 节点计算是独立地从 PS 节点获取模型参数,独立计算梯度并更新。采纳同步随机梯度降落算法(SGD)算法的数据并行训练是一种十分风行的办法。
每个节点的工作大抵能够分成三步:
- 节点从 PS 节点获取最新的模型参数,对各自负责的训练数据进行前向流传。
- 各个节点独立地对不同局部的训练数据进行反向流传,失去每个模型参数的梯度。
- 对各个 worker 节点的梯度计算结果进行同步,利用更新模型的参数
而后一直的循环迭代。
节点的每一次迭代都须要通过网络进行海量参数的同步,这对网络带宽提出了十分高的要求。解决这个问题的一个办法是减少网络的带宽,但这样做意味着极高的老本,同时随着模型体量的增大,老本也无法估量。因而,咱们应该寻求在无限带宽下的解决方案。
近年来一种风行的计划是梯度压缩,然而这种计划的毛病在于失落了一部分信息,可能会影响到模型的准确度。
还有一种办法,就是进步网络带宽的利用率。在训练的过程中,如果咱们在每次迭代实现后才去同步梯度,就会导致网络流量爆炸性地增高,而在 worker 节点计算的过程中,网络却根本处于闲暇状态。因而,咱们能够将曾经计算出来的梯度在 worker 节点计算其余层梯度的时候发给 PS 节点,即让 worker 节点与 PS 节点之间的通信和 worker 节点的反向流传同时进行,这样,网络带宽就能够失去更无效的利用。一些深度学习框架曾经实现了这一点,比方 TensorFlow、MXNet 和 Caffe2。
局限性与优化
作者等人在工作中发现了以上计划还存在肯定的局限性,通过优化,模型对网络带宽的利用率和计算速度能够进一步提高。
反向流传中参数传递的优先级
在神经网络模型的训练中,咱们通常是:反向流传——用反向流传所得的参数进行前向流传,更粗疏一点,从最初一层开始进行反向流传的计算,再从第一层开始前向流传,如下图所示。
在第 N 次迭代中,咱们从输入层开始依据 Loss 计算出梯度并更新 L4 层的参数,而后递归地求出输出层即 L1 层的梯度同时更新整个模型的参数,而后咱们从输出层开始,进行 N+1 次的迭代,利用更新后模型的参数一层一层地计算,直到取得输入层的后果,而后进行再进行反向流传。
咱们能够察看到一点,在迭代的过程中,最先计算出来的参数(L4 层的参数)总是最初被应用,而反向流传最初计算出来的参数却最先被前向流传所应用。咱们发现在神经网络的计算过程中,各个层的参数从取得到应用两头的距离是不同的,层数凑近输入层,这一距离也越大。在以往的分布式训练中,参数往往在某一层的反向流传完结时就开始同步,这就有可能导致 L2 层的参数还没有同步完,然而 L1 层曾经反向流传完结,不得不期待 L2 层实现同步,L1 层实现参数同步而后再承受 PS 节点的参数更新,能力开始进行 L1 层的前向流传。这样,就会导致前向流传和反向流传之间的距离过大。
所以,咱们认为,在参数的同步中,层数低的层相比层数高的层,应该具备更高的优先级。
上图中(a)代表以往的同步机制,咱们对其进行改良,优先同步较低的层的梯度,如(b)所示,当 L1 层的梯度计算实现,然而更高层的参数还没有实现同步时,优先进行 L1 层的参数同步,这样就缩短了反向流传和正向流传之间的距离,然而并没有减少网络的负载。
参数同步中的粒度选取
参数同步所需的通信工夫次要由三局部组成:
- 梯度从 worker 节点传输到 PS 节点的工夫
- PS 节点利用梯度更新模型参数所需的工夫
- PS 节点发送更新完的参数到各个 worker 节点
就如之前形容的一样,以往咱们以层为粒度去进行参数同步,如图(a)所示,通过实现数据的传输和计算并行执行来尽可能地利用闲暇的网络带宽,缩短通信所须要的工夫。
然而在模型中,如果有一层的参数十分多,比方图(a)中的 L2 层,它实现参数同步所需的工夫每一步都是 L1 和 L3 的三倍,咱们会发现他会拖慢参数同步,或者说「阻塞」了参数的传递。比方在工夫为 4 时,只有梯度的传输,却没有进行任何参数更新的计算。这是因为咱们的参数同步是以层为单位,每一层中参数的更新必须要等到该层所有的节点的梯度都传输实现,然而咱们并不需要等到接管完所有节点的梯度后再开始更新参数。
所以,咱们能够采取更小的参数同步粒度,比方,将 L2 层的参数分成 3 份,独自地进行参数同步,如(b)所示。通过采取更小的粒度,咱们能够尽可能地晋升带宽的利用率,直观来讲就是增大图中不同层之间的重合度。
总结
以上两点就是 P3 采取的优化形式,作者在 MXNet 的根底上实现了这一机制,有趣味的同学能够拜访 GitHub 浏览相干源码。依据作者的测试,应用 P3,ResNet-50、Sockeye、VGG-19 等模型的训练效率别离晋升了 25%、38%、66%。这种同步机制的长处在于它与其余的优化形式并不抵触,且不会影响模型的精度,然而它对分布式模型训练效率的晋升也无限,且并不是所有的模型都有显著的晋升,特地是模型较小或者网络带宽非常受限时。
参考文献
- https://mlsys.org/Conferences/2019/doc/2019/75.pdf
- https://github.com/anandj91/p3