深度神经网络(Deep Neural Networks, 简称DNN)是近年来机器学习领域中的研究热点,产生了广泛的应用。DNN具有深层结构、数千万参数需要学习,导致训练非常耗时。GPU有强大的计算能力,适合于加速深度神经网络训练。DNN的单机多GPU数据并行框架是腾讯深度学习平台的一部分,腾讯深度学习平台技术团队实现了数据并行技术加速DNN训练,提供公用算法简化实验过程。对微信语音识别应用,在模型收敛速度和模型性能上都取得了有效提升——相比单GPU 4.6倍加速比,数十亿样本的训练数天收敛,测试集字错率降低约10%。目前基于此框架训练的模型成功上线到微信语音输入法、微信语音开放平台和微信语音消息转文字。
1.DNN数据并行导论
1.1.典型应用分析:语音识别
语音识别是深度神经网络获得成功的一个应用范例。
语音识别应用,简单来说由声学模型建模,语言模型建模以及解码三部分构成。其中声学模型用来模拟发音的概率分布,语言模型用来模拟词语之间的关联关系,而解码阶段就是利用上述两个模型,将声音转化为文本。神经网络具有模拟任何分布的能力,深度神经网络比浅层神经网络表达能力更强,它模拟了人脑的深层结构,能够更准确地“理解”事物的特征。因此相较于其他方法,深度神经网络可以更为准确地模拟声学模型和语言模型。这里将深度神经网络应用于语音识别中的声学模型建模。
图 1揭示了一个深度神经网络表达的具有4个隐藏层的声学模型结构,训练这样的具有深层结构的模型,其优势在于逐层的特征学习过程是由初级到高级的过程:第一层学习初始特征(例如最基本的发声),在后面的层次逐渐学习到越来越高级的特征(例如声音的组合),直到通过模型的输出层来有效地识别声音。
1.2.现有的加速方法
腾讯深度学习平台技术团队在语音识别研究中率先引入了GPU技术用于DNN训练,获得了良好的成果,相比单台CPU服务器达到千倍加速比。随着训练数据集扩充、模型复杂度增加,即使采用GPU加速,在实验过程中也存在着严重的性能不足,往往需要数周时间才能达到模型的收敛,不能满足对于训练大规模网络、开展更多试验的需求。目前服务器上安装多个GPU卡已经非常普遍,在通用计算领域使用多GPU并行加速技术扩展计算密集型应用程序的并行性、提高程序性能也是越来越热门的发展方向。
由于语音业务中DNN模型采用多层全连接的网络结构,腾讯深度学习平台技术团队在单机多GPU模型并行的实践中发现拆分其模型存在较大的额外开销,无论采用普通模型拆分还是流式控制,扩展性有限:相比GPU的计算能力,如果模型参数量不能匹配,模型并行不能有效地利用多个高计算能力的GPU卡,表现为使用2GPU时已有较好的性能提升,但使用更多GPU却无法取得更好效果。
腾讯深度学习平台技术团队考虑到上述问题,在腾讯深度学习平台的DNN多GPU并行训练框架中,选择了数据并行的技术路线,完成了升级版的单机多GPU数据并行版本。
本文描述了多GPU加速深度神经网络训练系统的数据并行实现方法及其性能优化,依托多GPU的强大协同并行计算能力,结合数据并行特点,实现快速高效的深度神经网络训练。
1.3.框架设计目标
由于训练深层网络使用的训练数据规模庞大、计算开销大,从而训练过程收敛难,训练用时久,通过开发多GPU数据并行版本期望达到下述目标:充分利用单机多GPU计算资源和DNN的数据并行特性,加速模型训练过程;提供默认的深度学习算法实现,以帮助提升语音识别准确率;提供更好的易用性支持,方便进行模型训练。
上述目标完成后,系统可以支持目标模型的快速训练,达到更好的收敛效果。另外,作为深度学习平台中的DNN数据并行框架,其训练算法具有一定的通用性,可通过简单配置快速适用于其他DNN应用场景中。
1.4.挑战
在语音识别应用中,深度模型包含数万神经元,采用全连接结构,具有数千万参数需要训练,计算量大;需要海量语音数据进行训练,在避免过拟合的前提下提高模型准确率、提高模型泛化能力。因此,如何充分利用计算资源实施数据并行以加速训练是框架设计首要解决的问题。
数据并行中参数交换容易成为整体性能瓶颈,因为在参数交换时需要将各个Model Replica在本次mini-batch训练中得到的梯度合并后用于更新参数服务器上的模型,之后再将最新模型推送到各个数据并行单元上用于下一轮计算。如何解决参数交换瓶颈以提高性能,成为并行方法设计的重中之重。
自适应学习率算法对于随机梯度下降(Stochastic Gradient Descent, 简称SGD)过程有利于加速收敛并获得更好的结果。但是它需要对模型中每个参数存储helper_sum并频繁更新对应的学习率,影响性能。因此,如何将其有效地应用到数据并行框架中,是我们所需要解决的另一个重点问题。
2.系统概述
如何数据并行?
数据并行:指对源数据集合中的元素同时(即并行)执行相同操作的情况。在数据并行操作中,将对源数据集合进行分区,以便多个并行处理单元能够同时对不同的子数据集合进行操作。
图2揭示了从单GPU训练到多GPU数据并行训练的变化,主要在于:单GPU每个周期训练1个mini-batch,mini-batch训练结束后即顺带在GPU显存中完成了更新模型参数的操作;在多个GPU同时训练多组mini-batch数据,每个数据并行组(Worker Group)充分利用本组上独占的GPU资源,在mini-batch训练结束时还需要一个将参数从各个GPU上交换并更新的过程,最终使得每个GPU上都持有最新模型副本,继续进行下一个周期训练过程。
多GPU并行系统从功能上划分为用于读取和分发数据的Training Data Dispatcher和用于做数据并行训练的GPU Worker Group,如图3所示。训练数据从磁盘文件读取到CPU主存再拷贝到GPU显存,故此设计在各Worker Group计算每batch数据时,由Training Data Dispatcher从文件中读取并分发下一batch数据,以达到用计算时间掩盖I/O时间的设计目标。
3.GPU Worker Group: 数据并行的承载体
数据并行以Worker Group为基本组织形式,调度来源于CPU,计算资源来源于GPU卡。GPU卡通常被看成是加速卡或协处理器卡,必须在基于CPU的主机上下文中被调用来做计算,因此1个CPU线程绑定1个Worker Group中的1张GPU卡能够发挥多GPU的并行效能。
在实际生产环境中,安装多GPU服务器的硬件体系结构如图4所示,示例中揭示了一个8 GPU节点服务器的硬件配置,每两个GPU Slot安装在一个GPU专用PCI槽位上再通过PCIe Switch将GPU Slot 0,1,2,3安装在一颗CPU上,GPU Slot 4,5,6,7安装在另一颗CPU上,两颗CPU通过IOH(Input Output Hub)连接。
在数据并行的场景下,将每颗GPU绑定一个Worker Group,即形成8路数据并行的并行化训练配置。
4.数据并行中参数交换的线形拓扑
4.1.数据并行的关键问题:参数交换是瓶颈
使用基于mini-batch的随机梯度下降算法时,每计算完成1个mini-batch后需要将本次计算得到梯度(图中记为Δw)应用到相应参数(图中记为w)上,朴素的参数更新公式为:
公式中,i是参数更新的次数,weight指代某个参数,ε是学习速率,Δw是本次BP计算出的梯度。
在数据并行的实现中,影响性能的瓶颈在于多GPU间的参数交换。这是因为按照参数更新公式来看,需要将所有模型replica的梯度交换到参数服务器并更新到相应参数上,而参数服务器的带宽成为瓶颈。
最优化的参数交换解决方案应具有的特征:尽量减少总的通信量;尽量减少所用交换周期数;每个周期用满PCIe总线通信带宽;GPU间数据传输没有等待;可扩展性强,适用于不同GPU数目的场景。
4.2.常见的解法
解决这一问题,直观的想法是依靠多GPU之间点到点的数据传输,即在每两个GPU之间建立数据传输连接,交换各自的ΔW。但是这样的解决方案提升的性能有限,主要在于任一GPU上计算出的ΔW在PCIe总线上需要多次传输才能更新到所有GPU的参数模型上,过多占用和消耗PCIe总线带宽。而随着GPU数增多,交换时间随之呈平方量级增加,这无疑是不适合的。
另一种常见思路是采用分治法+树形结构,为此可设计树形拓扑:模型2分片,奇/偶Worker Group负责归并模型不同分片,Worker Group间总是两两归并;当最终将2个分片归并结束后,开始反向的分发过程。但在多GPU场景下这种也存在着局限,主要在于每个归并周期后,总有一半GPU不再参与之后的归并过程,闲置了其计算能力和所在节点上的通信带宽。
4.3.当前最优解:线形拓扑
我们针对多GPU场景设计了参数交换的线形拓扑:
线形拓扑从空间上来看,如图6所示,将存储参数的矩阵、存储梯度的矩阵等量划分了Partition,Partition数量是Worker Group数的一半。令持有某一Partition最终累加结果的Worker Group(一般为Group ID为奇数的GPU),称之为该Partition的Partition Owner。对该Partition的更新参数操作会在该Partition Owner上执行,同时该Partition最新参数的分发过程也由该Partition Owner发起。
线形拓扑从时间上来看,如图7所示,将参数交换过程划分了周期,每个周期内将所有Partition从上游Worker Group向下游Worker Group推送一次,推送过程包括从上游Worker Group拷贝Partition数据和本地Merge两步操作,推送阶段的最后1个周期推送该Partition到Partition Owner上以使其持有参数的最新副本。推送所用周期数为数据并行组数-1。
之后参数分发过程,亦占用与推送相同的周期数分发Partition Owner上的最新副本给所有Worker Group。
我们比较容易给出线形拓扑的性能模型。PCIe总线带宽一定(设为W),取数据并行的Worker Group数目为2N,模型大小为M。在采用点到点全量参数交换的情景下,每两个Worker Group均需要进行对等的数据交换,因此数据传输的最短周期为2*(2N-1)次,每次在总线上传输数据量为M,故推导出参数交换用时2*(2N-1)*(M/W)。在采用线形拓扑的情景下,在每个组号为单数(1,3,5,…)的组上维护着整个模型参数相应的1/N,按照线形拓扑,单次数据交换中只传输了(1/N)* M的数据量,参数归并周期为2N-1,参数分发周期也为2N-1,因此推导出参数交换用时为2*(2N-1)*(M/(N*W)),仅是点到点用时的1/N(N=1,2,3,…)。可见,数据并行的并发量越大,线形拓扑的性能收益效果越显着。
线形拓扑可以很容易地扩展到偶数个数据并行组的参数交换,其收集(推送)用时随数据并行组数增长而缓慢增长,且具有上界——2T0,这说明线形拓扑非常适用于更多GPU做数据并行。
5.多GPU数据并行的自适应学习率(AdaGrad)算法
应用自适应学习率算法,对第i个位置上参数的学习率更新,需要借助helper_sum,其定义如下:
在数据并行情景下,helper_sum的跨组更新规则与的数据并行参数交换过程中的推送阶段完全相同,由于梯度是在Partition Owner上最先持有的完全累积结果,可以根据Adagrad参数更新公式Apply到参数上,而这时只用到了Partition Owner上的helper_sum,因此只需要在Partition Owner上持有其“Own”的Partition的最新helper_sum即可,其它非Partition Owner在推送之后即需要将helper_sum清零,以便为下一次计算重新累积所用。由于helper_sum不需要分发,则交换helper_sum的过程只需要一次推送阶段即可完成。
结合Adagrad算法实际应用场景:即helper_sum的累积其实是对每个学习率调整的量化过程,其本身具有一定的近似性。基于性能考量,实际项目中使用一种近似的helper_sum收集:在每个mini-batch结束后所有partition上做本地累积helper_sum计算,而在M个mini-batch结束后才将其推送到所属的Partition Owner完成最终累积。这样兼顾了算法效果和训练性能。
6.在语音识别上的应用
6.1.微信语音识别产品
微信中主要有三款语音识别产品:微信语音输入法、语音开放平台和语音消息转文字。多GPU数据并行框架训练的模型正在由这些产品使用。
6.2.模型训练实验性能
实验环境为一台搭载8核心Intel(R) Xeon(R) CPU E5-2640 v2 @ 2.00GHz的服务器,内存为48GB,服务器安装了6块NVIDIA Tesla K20c GPU,单GPU显存大小为4.8GB。
训练同样的语音目标模型,相比于单GPU,使用6GPU数据并行获得了4.6倍加速比。
6.3.模型准确率
采用6 GPU数据并行,使用数十亿语音训练样本,在训练目标模型的实验中,数个迭代时取得了在测试集上的最佳模型,取得了10%的字错率降低。同时相比模型并行训练,基于数据并行的腾讯深度学习平台可在数天内完成DNN模型训练。
6.4.易用性
框架提供良好的易用性支持,主要在于实验者不需要过多干预训练过程即可完成训练,实时获知训练进度和模型准确率等信息。框架主要的易用性支持包括:重要配置参数在运行时可手工改变,可自动衰减;按指定频率输出模型snapshot并进行自动化测试;训练中断点恢复,可从任意模型snapshot继续训练;微信监控帐号自动向实验者推送测试结果。
7.结论
本文描述了深度神经网络DNN的多GPU数据并行框架,通过多个Worker Group实现了数据并行,设计线形拓扑解决了参数交换性能瓶颈,实现了数据并行场景下的近似自适应学习率算法。此框架有效支持了微信语音识别,成功提升了微信语音识别的模型训练速度,并且模型字错率降低10%,模型全量上线到微信语音输入法、微信语音开放平台和微信语音消息转文字。