分布式机器学习 / 深度学习论文整理

给毕业论文方向找资料ing,虽说具体要做的东西目前还在思考比较多,从之前的 【整理一下看过的论文】 里面把相关的论文理出来了。

大致分成三个方面:

  • Distributed Machine Learning System
  • Distributed Deep Learning System
  • Large Scale Neural Network Training

虽说重点主要集中在后面两块上,不过其他方面的机器学习毕竟发展的时间比深度学习更早,分布式系统方面还是有参考价值的。

把第二三两部分分开整理主要考虑一个是偏框架和算法设计,一个是偏向针对某个具体的应用问题做的大规模实现。

Distributed Machine Learning System

2013 NIPS - More Effective Distributed ML via a Stale Synchronous Parallel Parameter Server

话说我第一眼看这个系列的文章还以为讲的就是深度学习了,后来才发现这些全是主要针对机器学习的。

分布式方法还是主要基于传统的 Parameter Server 对 Worker 的形式,但是提出了一种 SSP(Stale Synchronous Parallel) 模型来解决普通的同步或者异步模式下训练会有的问题。SSP 模型大致是说会在本地维护一个参数的 cache,每个工作的 node 直接从本地的 cache 中拿数据,跟 PS 之间的同步问题应该是另外处理,这样就把每个工作 node 等待网络的时间给降下来了。

Introduction 中首先分析了机器学习训练中可能有的问题:massive data volume 和 massive model size,数据量太大和模型太大这两个问题即使可以通过尽可能地缩减、压缩,也终有个尽头,未来总有解决不了的时候,因此不得不需要用到分布式的训练环境。

分布式机器学习系统需要解决的最终目标是:

  1. 最大化利用计算资源(把更多的时间花在运算上)
  2. 训练完之后要能支持 inference
  3. 保证正确性(保证分布式之后网络仍然是能够收敛的)

文中对 PS 的定义是:一个共享的键值对存储模型,同时要具备读取和更新参数的同步机制。共享的键值对存储方式能简化编程复杂度,数据同步是为了保证整个训练过程的正确性。

SSP 这种模型的重点在于像前面说的本地保留尽可能新的旧参数,这里给了个微软一篇技术报告的引用:

如果说同步可以达到更好的 quality,异步可以达到更好的 quantity 的话,SSP 是取了这两种方案的折中,最终比这两种都要有效。


规定每个 worker 运行时有个 clock 计数器(时间戳),记的是当前到了第几轮迭代。给定一个阈值 s,SSP 模型遵循以下几个规则:

  • 最慢的和最快的 worker 之间跑的参数之间的 clock 差不能超过 s,否则最快的 worker 就要强制等待后面较慢的 worker 算完了赶上来
  • 当一个当前 clock 值是 c 的 worker 提交一个参数更新时,那个更新的时间戳为 c
  • 当一个当前 clock 值是 c 的 worker 读取参数时,根据上述规则,它读取到的更新至少会包含 c-s-1 时间戳之前的所有更新内容
  • 一个 worker 读取到的更新总会比它自己产生的所有结果更新

事实上作者用 c 和 s 这两个定义就把 BSP 和异步给总结到一起了。如果 s 为 0,相当于所有的 worker 都是完全同步的,当 s 是无穷大的时候,就是完全异步的。

这个 s 就是 SSP 模型中需要 overlap 的部分,s 太小则可能经常有些 worker 需要等待,并行性提不上去,s 太大影响问题整体的收敛率。


具体实现上,作者用了一个类似 cache 页表的 SSP table,思想大致也是类似的。在多个 worker 跑在单个节点中的情况下,节点内还可以再多做一层线程间的数据 cache。

2014 ATC - Exploiting bounded staleness to speedup Big Data analytics

这篇 paper 的内容是上面那篇的后续研究(话说作者都差不多),大体上是对上篇内容作了更多的补充和提升。作者在实验中发现应用了 bounded staleness 思想的 BSP 模型到最后效果跟 SSP 是差不多的,因此对这其中的详细情况和原因也作了深入分析。

引入 bounded staleness 思想的 BSP 模型这里成为 A-BSP,BSP 是每次迭代之后一个大同步,A-BSP 就是把这个限制放开点,每 n 次迭代之后一个大同步。用上面一篇提过的归纳方式,BSP、A-BSP、SSP 都可以归到一起。

SSP 说起来确实有点像是在 A-BSP 的基础上做个流水线的感觉。当整个分布式系统中,各个线程做的任务不太平衡,有明显较慢的 worker 存在时,SSP 能更好地提高并行度(负载均衡?)。但 SSP 相对 A-BSP 的通信次数是更多的,当各个 worker 的运行速度差距很小时,可能用 A-BSP 会有更好的效果。

这里用来维护数据 cache 的数据结构叫 LazyTable,其实就是前面 SSP Table 的升级版,实现大致都是类似的。

另外这里还做了预取和容错。

2014 SoCC - Exploiting Iterative-ness for Parallel ML Computations

To be read.

2014 OSDI - Scaling distributed machine learning with the parameter server

To be read.

2015 SoCC - Managed Communication and Consistency for Fast Data-Parallel Iterative Analytics

To be read.

2015 - Distributed Machine Learning via Sufficient Factor Broadcasting

SFB。

To be read.

2015 - Efficient Machine Learning for Big Data: A Review

机器学习与大数据结合方面的一篇综述。

To be read.

2015 - Petuum: A new Platform for Distributed Machine Learning on Big Data

一种分布式机器学习的平台设计。

To be read.

2015 EuroSys - Malt: distributed data-parallelism for existing ml applications

一个叫 Malt 的库,用于把常用的机器学习应用从单机改造成分布式的。

To be read.

2015 SoCC - Managed Communication and Consistency for Fast Data-Parallel Iterative Analytics

一套叫 Bosen 的分布式机器学习系统。

To be read.

2016 EuroSys - STRADS: A Distributed Framework for Scheduled Model Parallel Machine Learning.

To be read.

2016 UAI - Lighter-Communication Distributed Machine Learning via Sufficient Factor Broadcasting

SFB。

To be read.

2017 - Machine learning on big data Opportunities and challenges

To be read.


Distributed Deep Learning System

其他资料

2012 NIPS - Large Scale Distributed Deep Networks

Google 的第一代深度学习系统 Distbelief,由 Jeffrey Dean 大佬带头,其实是 TensorFlow 的前身。

现在说的深度神经网络最初的来源就是传统机器学习里面的受限玻尔兹曼机(Restricted Boltzmann Machine,RBM)以及多层感知器(Multilayer Perceptron,MLP)等等想法,这俩演变出来了一个叫深度信念网络(Deep Belief Network,DBN)的东西,基本跟今天的 DNN 已经很像了。Distbelief 里面的 Belief 指的应该就是 DBN 吧。

出发点基本跟后来的文章大同小异,文章的重点在于:

  1. Downpour SGD:前面这个单词是描述倾盆大雨的,不知道整个词组应该怎么翻译比较好;
  2. 基于 Sandblaster 框架实现了一个 L-BFGS,用于处理整个训练过程的数据并行和模型并行。

相比普通的 SGD + 普通的 L-BFGS 实现要快上不少。

异步 SGD 之前在机器学习领域很少被用在非凸的优化问题上,但是经过试验验证之后发现异步 SGD 用在神经网络上效果很好,尤其是配合 Adagrad 这种学习率修正算法的时候。然后在资源足够的情况下,L-BFGS 的性能不会弱于 SGD。

论文中做到的最大规模是把一个模型拆到 32 个节点上进行模型并行。

2013 ICML - Deep Learning with COTS HPC

首次把分布式机器学习里面的数据并行模型并行引入深度学习。

主要实现在 InfiniBand 网络上,然后偏重在模型并行上。

To be read.

2014 ICASSP - On parallelizability of stochastic gradient descent for speech DNNS

这篇文章是从理论上对比了模型并行和数据并行中分布式 SGD 训练的效率,指出增大 minibatch 的大小可以提高数据并行训练的效率。

To be read.

2014 OSDI - Project Adam: Building an Efficient and Scalable Deep Learning Training System

微软在分布式 DL 训练方面做的工作。

To be read.

2014 Proceedings of the VLDB Endowment - Mariana: Tencent Deep Learning Platform and its Applications

腾讯做的一个叫 Mariana 的深度学习平台。

To be read.

2015 ACM MM - SINGA: Putting Deep Learning in the Hands of Multimedia Users

一套叫 SINGA 的分布式深度学习框架。

To be read.

2016 - Asynchrony begets momentum, with an application to deep learning

分析了异步与动量法调整的学习率之间的影响关系。

动量法是一种梯度下降里面对学习率自动调节的方法。

To be read.

2016 - How to scale distributed deep learning

用 ImageNet 对比了同步和异步 SGD 的实测结果,指出可能在更大规模下其实同步 SGD 效果更好。

To be read.

2016 SoCC - Ako: Decentralised deep learning with partial gradient exchange

去中心化(不再采用 PS-Worker 方式)的分布式深度学习思路。

To be read.

2016 Eurosys - GeePS: Scalable Deep Learning on Distributed GPUs with a GPU-Specialized Parameter Server

这篇文章很厉害了,主要内容是说做了一套叫 GeePS 的 Parameter Server 机制,主要针对 GPU 做了特别的优化和改进,克服了数据并行和模型并行,BSP 和异步这些老方法中存在的问题,最终结果性能爆炸。GeePS 还支持在卡上跑超过显存容量的网络,直接解决了对模型并行的需求。

背景介绍部分分析了一下 Parameter Server 模式存在的问题,这里也有提到前面 13 年那篇 SSP 模型方面的工作(…其实这篇论文还是同一拨人做的…)。要应用 PS 模式到 GPU 上,采用多个 worker 配合多个 ps,每个物理节点内都有 ps 和 worker 这种形式会比较合适。

但是直接简单地把 ps 搬到 GPU 上效果非常不好,后文接下来就是讲他们如何解决这个问题,即他们提出来的 GeePS 是怎么做的。

第一个优化策略是在 GPU 上做一个参数 cache,嗯这个思想大概跟往异步 PS 里面引入本地 cache(应用 SSP 模型)是一个道理。因为前面的性能瓶颈主要在每一次推送参数更新上了,引入了 CPU 跟 GPU 之间的数据传输之后总会把整个计算过程卡下来。

这种方法提升性能的关键在于能够成功地把计算和 CPU/GPU 的数据拷贝给 overlap 开,这样就能最大化 GPU 的使用率啦,GPU 只要拿到了新的 input 数据就能一直跑。

第二个策略是数据的输入和参数的更新都是以 batch 为单位的,利用了 GPU 的 SIMD 特性,增加了数据的吞吐量,这一块详细的要见他们前面的一篇文章(Exploiting Iterative-ness for Parallel ML Computations)。

第三个就厉害了,目测应该工作量挺大的。为了解决模型太大,GPU 上放不下的问题,他们手动维护了一个 GPU 和 CPU 之间的内存池,每次把不用的数据换到主存上,把下一波计算需要用的数据换到 GPU 上。

用手动维护的内存池完全接管整个 GPU 的内存分配、释放操作,CPU 跟 GPU 之间的数据传输用另外一个线程在后台完成,把计算时间和数据拷贝延迟完全 overlap 开。由于神经网络层与层之间的顺序性是显示存在的,因此数据在 GPU 显存上的换入换出就是完全可以做到的了。

第四点是对 PS 模式下异步方式的思考,虽说把 BSP 改成异步的可以增加计算资源的利用率,但是收敛速度会放慢是肯定的,之前的不少研究也是在这两个方面作了取舍,才能让最终训练到相同效果的总体时间更短。这篇文章在同步延迟能够保证的情况下,测试结果偏向于用 BSP 收敛效果会更好。

中间的详细实现先放着,留待之后回来看。

2017 ATC - Poseidon: An Efficient Communication Architecture for Distributed Deep Learning on GPU Clusters

emm…这篇文章跟上一篇还是同一拨人做的。Motivation、目标什么的基本上差不多,工作方向上从不同的角度出发来做。

文章首先指出了限制分布式深度学习可扩展性的两个瓶颈:

  1. 每次更新的梯度都可能是大矩阵,很容易就把网络带宽给占满;
  2. 由于神经网络运算的迭代特性,在完成一轮迭代之后才更新参数。因此其通信表现是短时间内有一个通信量的暴增,而其他时间没有通信。

本文解决问题的思路也从这两点开始出发:

  1. 把要更新的梯度矩阵做一定的划分,通过重新调度,在时间上把整个通信平摊掉;
  2. 想办法减少每次更新的梯度矩阵的大小,从整体通信量上做文章。

最后要达到的效果呢,也是分两方面:首先整个系统的吞吐量增加了,同时迭代的收敛速度并不受影响,不需要增加迭代次数就能达到一样的效果。

减少梯度矩阵大小用的是一个叫 SFB(Sufficient Factors Broadcasting)的技术,具体的文章在这里

作者认为核心的瓶颈还是主要在通信上。

这里给出了一个对 Alexnet 的粗略分析(不是特别准确,但是基本上是同一个量级),假定计算跟通信能够完全 overlap 开,用 Taitan X 节点来分布式训练大约也要至少 26 Gbps 的网络带宽,这个压力对一般的以太网来说基本上是很难应对的。当然 overlap 计算和通信这事本身就很难做到了。


作者首先分析了整个训练过程的思路:

定义训练第 l 层网络的前后向为 $f_t^l$ 和 $b_t^l$,那么整个训练的计算部分是这样的:

$$C_t = [f_t^1, f_t^2, … , f_t^L, b_t^L, b_t^{L-1}, … , b_t^1]$$

加上通信同步部分,$O_t^l$ 和 $I_t^l$ 分别表示第 l 层网络参数的输出和输入(更新):

$$S_t = [O_t, I_t] = [O_t^L, O_t^{L-1}, … , O_t^1, I_t^L, I_t^{L-1}, … , I_t^1]$$

这样组成的一次 $C_t, S_t$ 就是一次迭代的完整过程了。

那么就提出了这里的第一个思路:

  • 分层把通信和计算给 overlap 开,这里称为无等待的反向传播算法(WFBP)

通信的数据依赖关系只在同一层内,即: $b_t^l$ 结束之后就可以马上做 $O_t^l$ 和 $I_t^l$ 了,即第 l 层的参数同步可以跟第 l-1 以及以后层的后向计算同时进行。示意图如下:

这种思路尤其适用于参数集中在后几层(例如后几层是全连接),然后计算集中在前几层(例如前几层是卷积)这样的网络(例如 VGG 和 AdamNet),这样就能把顶层的通信时间掩藏在底层的计算时间中。

大概是这种样子:

$$
\begin{align}
[C_t, S_t] = [f_t^1, f_t^2, … , f_t^L, b_t^L, &b_t^{L-1}, b_t^{L-2} … , b_t^1] \\
&[O_t^L, O_t^{L-1}, … , O_t^1] \\
&\qquad [I_t^L, I_t^{L-1}, … , I_t^1]
\end{align}
$$

但是这样对于带宽受限的网络来说仍然不够,所以有了接下来的第二个思路:

  • 采用 PS 和 SFB 混合的通信机制

正如上面所分析的,事实上不只是神经网络不同层的计算和通信可以无关,不同层之间的通信也是完全可以独立的,因此考虑对不同层数据的特点采用不同的方式进行组织通信。PS 模式或者 SFB 模式:

并且神经网络的结构是只要训练开始了,自始至终都不会再改变,因此可以事先算出参数的总量来估计整个网络会产生的通信开销,在训练开始前就能够选择合适的通信组织方式。

这里又举了个例子:

VGG19,假定 batch size K = 32,8 个 PS 和 8 个 Worker,参数均分在 8 台 PS 上,全连接层 M 和 N 都是 4096。2 个全连接层每一步迭代产生 2 * 4096 * 4096 = 34M 个参数。

PS 模式下:每个 Worker 每次要发送 34M 个参数,每个 PS 管 34M/8 个参数,但是要从 8 个 Worker 那里接收,所以总的通信数据量还是 34M。如果实际物理机就 8 台,每台上面跑一个 PS 和一个 Worker,那么每台机上本地更新 34M/8 的数据,每次要送出去 7/8 * 34M 的数据,再收回来 7 个 34M/8 的数据,一共 2 * 7/8 * 34M = 58.7M 的数据量。

SFB 模式下:(这种通信模式我还没细看,所以不知道为什么这么算)没有 PS,直接是 8 个 Worker 进行数据处理,每个节点需要负责的通信量只有 2 * K *(M + N)(P1 -1) = 2 * 32 * 8192 * 7 = 3.7M 的数据量。虽然收到数据之后要恢复成梯度矩阵需要额外的运算,但是这跟节省下来的通信时间相比是可以忽略不计的。

卷积层的更新梯度由于是不可分解的,并且是稀疏的,所以还是采用 PS 模式更好。

所以根据不同层的参数特性采用不同的通信机制的方法是有很大潜力的。


整个 Poseidon 系统的设计分成三个部分:

  • Coordinator:用于维护网络模型和集群设备之间的配置关系

集群中 worker 和 ps 的数量,对应的 ip 地址,网络模型的结构等等。负责建立各节点之间的通信端口,分析网络模型,决定哪些参数用 PS 哪些参数用 SFB。

当然这些数据是在初始化的时候就完成了。

  • KV store:一个共享内存的键值对存储部件,其实就是 Parameter Server

为什么这里的 PS 要突出”键值对“这个概念呢?

Poseidon 在这里做了一个操作,参数不是按照层来划分的(!!!),而是把所有的参数按照 2MB 划分之后再均分到各个 PS 上去,这样就能保证每个 PS 上面存储的数据量尽可能地一致,让各个节点需要的网络带宽尽可能地平均。

另外还有 checkpoint 的设计,保存多个阶段的参数用于容错恢复等等。

  • Client Library:用于适配到不同的深度学习框架中

对每个层都单独创建一个 syncer 负责处理其参数一致性。

在 CPU 上维护一个线程池(用于后台处理网络通信),在 GPU 上维护一个 stream 池(用于后台处理 CPU 和 GPU 之间的数据拷贝)。


之前作者的文章里面也提到了 BSP 的收敛性相对异步来说始终还是更稳定的,有了上面那个分层同步、通信几乎完全掩藏在计算背后的设计之后,BSP 跟异步之间的延迟差距可能已经能够减少到足以忽略的程度了。

因此在参数一致性方面的维护上,Poseidon 直接采用了 BSP 同步。

worker 这边,每个 client library 维护一个长为 syncer 数的 01 向量,每次迭代开始前初始化为 0,当一层的数据同步完了之后设为 1,当整个向量全 1 时就可以进入下一个迭代了。

PS 这边,KV stroe 在每次迭代开始前维护一个值为 0 的计数器,每当有一个 KV 更新计数加一,当计数器达到 worker 的数量时,发起一次参数广播。

整个训练过程的伪代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function TRAIN(net)
for iter = 1→T do
sync count = 0
net.Forward()
for l = L→1 do
net.BackwardThrough(l)
thread pool.Schedule(sync(l))
endfor
wait until(sync count == net.num layers)
endfor
endfunction
function SYNC(l)
stream = stream pool.Allocate()
syncers[l].Move(stream, GPU2CPU)
syncers[l].method = coordinator.BestScheme(l)
syncers[l].Send()
syncers[l].Receive()
syncers[l].Move(stream, CPU2GPU)
sync count++
endfunction

后面是 evaluation,测试结果就是很强…各方面都很强。

2015 - Poseidon: A system architecture for efficient GPU-based deep learning on multiple machines

这篇 paper 是在上面那篇发出来之前放在 arxiv.org 上的,应该算是正篇前的一些基础工作,看完 2017 年的正篇再看下这个。

2017 - Can Decentralized Algorithms Outperform Centralized Algorithms A Case Study for Decentralized Parallel Stochastic Gradient Descent

又一篇去中心化思路的文章。

To be read.

2017 ICML - Device Placement Optimization with Reinforcement Learning

To be read.

2017 - ChainerMN: Scalable Distributed DeepLearning Framework

下面列的那个 15 分钟跑完 ImageNet 的日本机构用的是他们自己写的框架,名字就叫 ChainerMN。

To be read.


Large Scale Neural Network Training

这个分类下面主要是实际应用层面的工作。

2013 ICASSP - Building High-level Features Using Large Scale Unsupervised Learning

谷歌做的无监督学习图像分类的工作。

在一个超过 1000 个节点的集群上用了模型并行和异步 SGD。

文中的网络叫稀疏深度自编码器(Sparse Deep Autoencoder),基本上跟现在的 DNN 差不多,应该是当时深度学习这个概念还没有完全定型。

实现方面没有具体写的很清楚,主要参看前面12年NIPS的那篇工作吧

2017 Facebook - Accurate, Large Minibatch SGD Training ImageNet in 1 Hour

Facebook 做的大规模 GPU 集群训练,顺便推一波 Caffe2。

256 块 GPU,1 小时内跑完整个 ImageNet 的数据集训练,想想都可怕。

这篇文章主要是从一个“炼丹师”的角度来写的,主要关注在学习率、minibatch 等等之间的关系,以及它们对训练带来的影响。文章的主要工作是提出了一种根据 minibatch 大小调整学习率的扩放规则,以及一种在训练时预跑的机制。

这些可能大多都是训练中总结出来的一些 tricks 吧。


随着网络模型和数据规模的不断增长,训练时间也跟着增长了,为了保证训练时间能够保持在一个有意义的限度之内,就需要一些额外的工作了。

文章的立足点是通过增大训练时的 batch size 来加快训练速度。例如 ResNet-50 这个网络通常大家采用的 batch 大小是 256,在 8 块 P100 上大约需要 29 个小时才能跑完整个 ImageNet 数据集。

但是如果加大 batch size 呢?改变 batch size 会影响到最终的收敛和训练结果的正确率

说实话,我们网络跑的少,这些问题还真不太懂……

文章接下来的工作就是通过调学习率等等其他的一些方法,把加大 batch size 带来的影响控制在一个可接受的范围内,最终做到 8192 个 batch 训出来的结果跟原本的效果持平。当然最重要的,batch size 增大了 32 倍,总的训练时间也能够降下来,用 256 块 GPU 在 1 小时内训完了整个 ImageNet!


为了维持训练结果的准确率,他们在过往积累的大量经验上得出了一个令人难以置信地简单却又有效的规则:

  • Linear Scaling Rule:minibatch 扩大 k 倍,学习率也扩大 k 倍。

其他超参数维持不变就好。

多次测试之后,可以发现应用了上面这个规则时,不同 minibatch 的 SGD 不仅最终准确率非常接近,而且训练的收敛曲线都是非常相似的。

但是在两种情况下,前面讨论的一些假定会有问题:

  1. 训练初始的几个 epoch 可能会引起网络参数巨变

    在某些网络中,如果一开始设的学习率太大,初始的几个 epoch 会产生过大的梯度,上面这条规则就可能不太适用了。为了解决这个问题,文章于是提出了预热训练的阶段。

  2. minibatch 的大小不能无限增长

    就拿前面 ResNet-50 为例,这个规则只够保证 minibatch 在增长到 8192 的时候能维持训练效果,再大就保证不了了。

接下来是训练预热的机制:

  • Gradual warmup:预训练时先用一个比较小的学习率,然后爬坡增长,逐渐增加到目标需要的 k 倍

经过实践调整之后,他们的实现里面是经过 5 个 epoch,学习率逐渐从$\eta$增长到$5\eta$。


分布式 SGD 在具体实现上还有很多细节的地方,可能稍微变动一下就会影响到整个模型的超参数,这里提了几个注意点吧:

  1. 权重衰减:交叉熵 loss 的扩放并不等价于学习率的扩放(?)
  2. 动量修正:在改变学习率之后再应用动量修正
  3. 梯度聚合:用整个 minibatch 的大小 kn 来均一化每个 worker 的 loss,而不是 n
  4. 数据清洗:先对训练数据做 shuffle 再把他们放到不同的 worker 上

关于我最关心的梯度聚合的实现,他们没有采用 Parameter Server 的形式,而是所有 worker 直接做 allreduce

Allreduce 分成 3 个阶段:

  1. 每个节点的 8 块 GPU 的数据合并到同一个 buffer 上
  2. 所有节点对数据进行汇总做 allreduce
  3. 每个节点的梯度更新完之后再广播到各自的 8 块 GPU 上

1、3 两个阶段的操作,如果数据量大于 256 KB 则用 NVIDIA 的 NCCL 库来完成,否则就各自把数据传回 CPU 再做汇总。

阶段 2 用到了递归二分倍增算法以及令牌环算法……嗯,基本上也没有什么特别的,就是想办法高效实现 all_reduce 和 all_gather。

软件栈用的是 Facebook 自家开源的 Gloo,具体的通信方面都是靠这个通信库来完成,就不涉及到具体的实现了(……)。以及 Caffe2。

硬件是 Facebook 的 Big Basin GPU 集群。每个节点是 8 块 NVLINK 的 P100(!!!DGX-1!!!),50 Gbit 的 InfiniBand

预估一下 ResNet-50 的数据量:大约参数量是 100MB 左右,单 P100 跑完一次大约 120ms,也就是峰值带宽大概要在 100MB * 2 / 0.125s = 12.8 Gbit/s 的程度。

后面的 evaluation 先不看了,,2333,,反正效果很好就是了,线性加速等等。

2017 - Extremely Large MinibatchSGD Training ResNet-50 on ImageNet in 15 Minutes

。。。上面 Facebook 用 256 块 P100 做了大 minibatch 的 ImageNet 训练之后,感觉军备竞赛就开始了。

这是日本的一个研究机构,用 1024 块 P100,15分钟跑完 ImageNet!


完成这个任务主要有两方面的挑战:

  1. 算法层面,使用更大的 BatchSize 之后,要想办法防止精度的损失;
  2. 系统层面,需要设计一套方案来有效地利用上可用的硬件和软件资源。

这里给了个表,对比了一下目前用 ResNet 跑 ImageNet 的几个工作:

Team Hardware Software Minibatch size Time Accuracy
MSRA(ResNet作者) Tesla P100 * 8 Caffe 256 29 h 75.3%
Facebook Tesla P100 * 256 Caffe2 8192 1 h 76.3%
SURFsara KNL 7250 * 720 Intel Caffe 11520 62 m 75.0%
UC Berkeley Xeon 8160 * 1600 Intel Caffe 16000 31 m 75.3%
This work Tesla P100 * 1024 Chainer 32768 15 m 74.9%

嗯…话说,UCB 最早发的文章也是在 KNL 上跑的,刚刚才发现他们当时最新的工作是用的 8160 跑的???(这 TM 可是通用处理器啊???害怕,下面那篇真得好好看看了)

具体的实现,这里说是参照 Facebook 的工作做的,比较额外的就是加大了 BatchSize,然后软件方面换了他们自己写的 Chainer 框架,因此这块写的比较简略。

NCCL 和 OpenMPI 意味着他们写的这个框架是基于 MPI 做的通信,而且还做了卡间数据传输。主要还是用的同步模型,然后做 Allreduce。

训练用的单精,然后划重点,为了减少通信的数据量,数据传输的时候用的半精浮点!!测试之后发现对结果影响不大(666666….)。

硬件方面,双路 E5-2677,8 块 P100 的配置,应该是没有 NVLINK 的,IB 用的 FDR(56 Gbps)。

2017 UC Berkeley - ImageNet Training in Minutes

接下来上台的是 UC Berkeley。

话说他们最早一篇论文写的是 24 分钟跑完,可能被上面那篇 15 分钟的刺激了一下,最近更新了一下把标题里面的 24 去掉了,把这个时间也缩短到了 10 分钟的量级。

文中使用了两种硬件方案:

  1. Intel Skylake CPU,应该就是前面提到的 Xeon Platinum 8160
  2. Intel KNL

大致的结果是:

Hardware Model Time
8160 * 1024 100-epoch AlexNet 11 m
KNL * 512 100-epoch AlexNet 24 m
8160 * 1600 90-epoch ResNet-50 48 m
KNL * 512 90-epoch ResNet-50 60 m
KNL * 2048 90-epoch ResNet-50 20 m

有一些前人的工作证明了异步的方式是不稳定的(例如 Revisiting Distributed Synchronous SGD 以及前面 Facebook 的工作等等),所以他们这里用的也是同步方案。通过加大同步 SGD 的 BatchSize 来加速。

在模型的选择上,他们提出了一个扩放率的概念,即计算和通信的比率,对 AlexNet 和 ResNet-50 这两个网络:

Model Communication
# parameters
Computiation
# flops per image
Comp/Comm
Scaling Ratio
AlexNet 61 Million 1.5 Billion 24.6
ResNet-50 25 Million 7.7 Billion 308

ResNet-50 的扩放率大概是 AlexNet 的 12.5 倍,所以 ResNet-50 的可扩放性更好,能达到更高的弱扩放效率。

然后 BatchSize 的改变是不会影响到网络模型的参数的,也就是说不管 BatchSize 多大,需要通信的量是不会变的,因此 BatchSize 越大,计算量越大,就能够更好地 Overlap 通信的延迟了。

问题在于 BatchSize 不能无限往上加,大到一定程度之后,准确率就降下来了,那么为了解决这些问题,就要增大学习率以及用上训练预热的机制(这些方法基本上跟前面 Facebook 的做法差不多)。跟进一步的是,这里用了一种叫 LARS(Layer-wise Adaptive Rate Scaling)的算法,达到了 Facebook 他们做不到的 BatchSize。


把一个算法扩大规模到更多的处理器上时,通常通信都会成为最大的 overhead。

这里从两个角度分析了通信比计算慢这一点,首先是硬件运算力(每个 flop 需要花费的时间,例如 P100 的峰值性能是 11TFlops 左右,$\frac{1}{11TFlops}$大约是$0.9*10^{-13}s$左右)会远小于理论传输速度(这里用的是$\frac{1}{Bandwidth}$,例如 56Gb/s 的 FDR,大约是$0.2*10^{-9}s$的水平),然后远小于延迟:

$$Time-Per-Flop << \frac{1}{Bandwidth}<<Latency$$

然后在 45nm 工艺的 CMOS 处理器上,通信消耗的能量也比计算更大:

Operation Type Energy(pJ)
32-bit Int Add Computation 0.1
32-bit Float Add Computation 0.9
32-bit Int Multiply Computation 3.1
32-bit Float Multiply Computation 3.7
32-bit Register Access Communication 1.0
32-bit SRAM Access Communication 5.0
32-bit DRAM Access Communication 640

能量这个角度比较神奇,感觉应该体现的不是很明确,因为计算这个过程本身肯定涉及到访存,更多的应该要对比网络传输吧。


设总的 epoch 数为 E,图片数为 n,BatchSize 为 B,网络参数为 |W|。

当 E 不变的时候,总的计算量是固定的,总的迭代次数是 $E*\frac{n}{B}$,通信量是$|W|*E*\frac{n}{B}$。当 BatchSize 增大之后,总迭代次数减少,那么通信次数也减少了,通信量减少。

因此增大 BatchSize 有利于网络向大规模进行扩展。


0%