您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 公司方案 > 为你的深度学习任务挑选最合适gpu
—为你的深度学习任务挑选最合适GPU查看原图拥有一个快速的GPU对深度学习的初学者来说是非常重要的,因为它可以使你迅速获得有助于构建专业知识的实践经验。本文为你的深度学习任务挑选最合适GPU,提供从性能到价格的全方位指南本文作者TimDettmers是瑞士卢加诺大学信息学硕士,热衷于开发自己的GPU集群和算法来加速深度学习。本文的最早版本发布于2014年8月,之后随着相关技术的发展和硬件的更新,Dettmers也在不断对本文进行修正,截至目前已经进行了5次较大的更新。机器之心今天呈现的这篇是其2016年6月25日的最新更新:「重新编辑了多GPU部分;因为不再有重大作用,去掉了简单的神经网络内存部分;扩展了卷积内存部分;对AWS部分进行了删节,因为不再有实效;增加了我对XeonPhi的看法;更新了GTX1000系列。」而除了GPU之外,深度学习还需要其它一些硬件基础,详情可参阅机器之心之前的文章《深度|史上最全面的深度学习硬件指南》。当你在深度学习中使用GPU时,你会一次又一次地为它带来的速度提升而感到惊叹:在一般问题中能获得相对于CPU快5倍的速度提升,在一些更大的问题中还能获得相对快10倍的速度提升。在GPU的帮助下,你可以更快地试验新的想法、算法和实验,并迅速得到反馈——哪些是可行的、哪些是不可行的。如果你对深度学习是认真的,那么你一定要使用GPU。但是,你应该选择哪一种呢?在这篇博客中我将指导你选择一款最适合你的GPU。拥有一个快速的GPU对深度学习的初学者来说是非常重要的,因为它可以使你迅速获得有助于构建专业知识的实践经验,这些专业知识可以帮助你将深度学习应用到新问题上。没有这种迅速的反馈,从错误中汲取经验将会花费太多时间,会使人在继续深度学习的过程中感到受挫和沮丧。在GPU的帮助下,我很快就学会了如何在一系列Kaggle竞赛中应用深度学习,并且在PartlySunnywithaChanceofHashtagsKaggle竞赛上获得了第二名,竞赛内容是通过一个给定的Twitter预测气象等级。比赛中,我使用了一个相当大的带有修正线性单元(rectifiedlinearunits)和dropout的两层深度神经网络进行正则化(regularization),而且勉强才能塞进我的6GBGPU内存里。应该使用多个GPU吗?在GPU的帮助下,深度学习可以完成很多事情,这让我感到兴奋。我投入了到多GPU的领域之中,用InfiniBand40Gbit/s的互连组装了小型GPU集群。我非常激动地想了解多个GPU能否获得更好的结果。我很快就发现,在多个GPU上,不仅神经网络难以进行有效的并行化,对普通的密集神经网络加速效果也很一般。小型神经网络可以并行并且有效地利用数据并行性,但对于大一点的神经网络,例如我在PartlySunnywithaChanceofHashtagsKaggle比赛中使用的,就几乎没有加速效果。随后,我进一步试验,对比32位的方法,我开发了带有模型并行性的新型的8位压缩技术,该技术能更有效地并行处理密集或全连接的神经网络层。然而,并行化失败了。我天真地为一系列问题对并行算法进行了优化,但只发现即使有优化过的自定义代码,它的效果也并不好——考虑到你所付出的努力。你需要非常了解你的硬件及其与深度学习算法交互的方式,这样你一开始就能衡量你是否可以受益于并行化。查看原图我的电脑主机配置:你可以看到三个GXTTitan和一个InfiniBand卡。对于深度学习来说,这是一个好的配置吗?然而,在并行化上还有一些不那么专业的问题。例如,卷积层很容易并行化和很好地扩展。很多框架也支持这种并行性;对大多数框架来说(比如TensorFlow、Caffe、Theano和Torch),如果你使用4个GPU,通常会加速约2.5-3倍;而对于优化过的研究代码,大约会有3.6-3.8倍的加速。微软的CNTK拥有最好的并行化性能,其与研究代码相近。CNTK有一个缺点:它目前非常难使用,因为其使用了配置文件(configfiles),而非库API。目前我在微软研究院做实习生,我将致力于CNTK,我可以告诉您,API与并行性能都将会获得显著的提升。这些变化使得在多GPU和多计算机下的并行化可以达到使普通用户能很容易受益于不同类型深度学习模型的快速训练的程度,无论是卷积网络、循环网络、还是全连接网络。使用多GPU的另外一个好处是你可以分别在每个GPU上运行多个算法或实验。其速度没有变快,但你能一次性通过使用不同的算法或参数得到更多性能信息。如果你的主要目标是尽快获得深度学习经验,这是非常有用的,而且它对想同时测试新算法的不同版本的研究者也非常有用。如果你想要学习深度学习,这对你的心理是很重要的。执行任务的间隔以及得到反馈信息的时间越短,大脑越能将相关的记忆片段整合成连贯的画面。如果你在小数据集上使用独立的GPU训练两个卷积网络,你就能更快地知道什么对于性能优良来说是重要的;你将更容易地检测到在交叉验证误差的模式,并正确地解释它们——即对于哪些你需要调整的模式,你需要添加、移除或调整哪些参数与层。所以总的来说,一个GPU对所有任务来说就已经足够了,但多个GPU对于加速你的深度学习模型来说越来越重要。如果你想快速学习深度学习,多个廉价的GPU也很好。应该使用哪种加速器呢?NVIDIA、AMD、或XeonPhi?NVIDIA的标准库使得在CUDA中建立第一个深度学习库很容易,但没有适合AMD的OpenCL的那样强大的标准库。目前还没有适合AMD显卡的深度学习库——所以只能选择NVIDIA了。即使未来一些OpenCL库可用,我仍会坚持使用NVIDIA:因为对于CUDA来说,GPU计算或者GPGPU社区是很大的,而对于OpenCL来说则较小。因此,在CUDA社区,好的开源解决方案和为编程提供可靠的建议是现成的。此外,NVIDIA公司现在对深度学习抱有很大信心。他们押注深度学习在未来十年会发展壮大,但你在AMD公司身上就看不到这样的信心。至于XeonPhi,其广告宣称你能够使用标准的C代码,并可将代码轻松转换成加速过的XeonPhi代码。该功能听起来很有趣,因为你可能认为你可以依靠庞大的C代码资源。然而,事实上,其只支持非常小部分的C代码,因此该功能并不真正有用,大部分的C运行起来是很缓慢的。我曾研究过超过500个XeonPhi的集群,遭遇了无止尽的挫折。我不能运行我的单元测试(unittest),因为XeonPhi的MKL(数学核心函数库)并不兼容NumPy;我不得不重写大部分代码,因为英特尔XeonPhi编译器无法让模板做出适当约简。例如,switch语句,我不得不改变我的C接口,因为英特尔编译器不支持C++11的一些特性。这一切导致了在没有单元测试的情况下来执行代码的重构。它花了很长时间。这真是地狱啊。随后当我的代码被执行时,一切都运行得很慢。如果你的操作的张量(tensor)的尺寸连续变化,线程调度器(threadscheduler)中的漏洞或问题会削弱性能。例如,如果你有不同大小的全连接层或dropout层,XeonPhi会比CPU还慢。所以,如果你想做深度学习,远离XeonPhi!了解卷积神经网络的基本内存需求当你在选择合适的GPU时,你得知道自己使用深度学习所要解决的问题需要多大的内存。因此接下来的两段文字会探讨卷积神经网络的内存消耗,让你可以确保自己的GPU有足够满足需要的内存,但又不会太多,这样能节省点钱。卷积神经网络的内存需求非常不同于简单的神经网络。你可能会认为前者的参数更少因此需要更少内存。如果只是保存网络文件,这没什么不对,但要想训练它的话情况就不同了。每个卷积层的激活(activation)和误差(error)相较于简单的神经网络来说都是巨大的,而正是它们占用了内存的主要部分。将激活和误差的大小加起来,我们就可以确定出大概的内存需求。然而要确定网络中哪种状态下激活和误差的尺寸大小是很难的。一般来说,前几层网络会占用很多内存,所以主要内存需求就来源于你的输入数据大小,因此可以率先考虑你的输入数据。通常ImageNet使用的输入维度(inputdimensions)是224×224×3,即224×224像素的3色信道图片。要在ImageNet上得到当下最先进的结果至少需要12GB内存,而在一个112×112×3维的类似数据集上我们可能只需4-6GB内存。另一方面,对于一个输入尺寸为25×75×75×3的视频数据集来说,12GB内存可能远给不了你想要的好效果。然而另一个重要方面就是数据集中的样本数量。比如你只取了ImageNet数据集图像中10%的样本,然后你的模型很快就会过拟合(只是没有足够多的样本来很好地训练),因此你那个消耗远远更少内存的小网络将足以与卷积网的性能媲美,所以4GB左右或更少的内存对于这项任务来说都绰绰有余。这就意味着图像越少,反过来所需内存就越少。标签的分类数量也是同样的道理。如果你从ImageNet数据集中只选取了2个分类来建立模型,那么相较于拥有1000个分类的模型,它将消耗更少的内存。这就是这样:如果你有更少的需要彼此区分的分类,那么过拟合就会出现得快得多,或者换句话说,相比于区分1000个分类,区分2个分类所需的参数要少得多。有关这些准则的一个实际例子是Kaggle的浮游生物检测比赛。起初我认为,用自己的4GPU系统来参加比赛可能会有巨大优势。我以为自己或许能够在很短时间内训练出一个庞大的卷积网络——还有一点就是别人都缺少这样的硬件。然而由于数据集过小(50×50像素,双色信道,40万张训练图像;大约100个分类),我很快意识到即使对于一个大小刚好够放入一个训练很快的小GPU的小网络来说,过拟合也是一个问题。所以多个GPU并没有多少速度方面的优势,而大GPU内存更没有任何优势可言。因此对于这种任务,一个4-6GB内存的小GPU就足以达到很好的效果。虽然此例中我的内存是足够的,但你最终会遇到内存不足的情况。然而你并不需要为这个问题而买一个新GPU,可能只需使用一个简单的内存减小技术(memoryreductiontechnique)。内存减小技术及其效果一种方法是使用更大步态(strides)的卷积核(convolutionalkernels),也就是不对每个像素都应用批形式的(patch-wise)卷积,而是针对每2个或4个像素(即2或4个步态),这样就能产生较少的输出数据。输入层通常使用这种方法,因为它消耗了大部分的内存。另一种减少内存占用的诀窍是引入一个能够减少维度的1×1卷积核层。例如96个1×1的卷积核能够使64×64×256大小的输入数据降为64×64×96。还有一个显著的技术是池化(pooling)。一个2×2的池化层将减少四层的数据量,从而大大减少了后续层的内存占用。如果这些方法都不管用,你总是可以尝试减少mini-batch的大小。mini-batch尺寸是一个非常重要的内存影响因素。大小为64的批(batch)会比大小为128的批减少一半内存消耗。然而训练时间可能也会更久,特别是在训练的最后阶段,为了得到准确的梯度,它显得更加重要。大多数卷积运算也为大小为64或更大的mini-batch进行了优化,因而从32大小的批开始,训练速度会大大减小。所以缩小mini-batch的大小到或者甚至低于32,只应作为最后的对策。另一个经常被忽视的方法是改变卷积网络所使用的数据类型。将32位换为16位,你就可以轻松减半内存消耗且不会降低分类性能。将它运用在P100Tesla卡中,这甚至能给你带来巨大的提速。那么将这些内存减小技术应用在实际数据中会怎样?如果我们采用128大小的批,3色通道的250×250像素图片(250×250×3)做为输入,3×3卷积核增长步长为32,64,96…,则我们将有大致如下、仅包含误差及激活的内存占用情况:92MB→1906MB→3720MB->5444MB->…此时内存将很快被挤爆。如果现在我们使用16位而非32位的数据类型,上面的数字就可降为一半;
本文标题:为你的深度学习任务挑选最合适gpu
链接地址:https://www.777doc.com/doc-4616913 .html