摘要
智能设备和可穿戴设备都将受益于深度学习算法(比如CNN)的准确性和可扩展性。然而,性能和能耗等现实的问题使得在移动端设备上这类密集计算的算法变得非常受限。我们开发了CNNdroid这个GPU加速库,可以在Android设备上实现CNN网络的训练。通过实验,CNNdroid在移动设备上实现了60倍速的提升,以及130倍速的节能。CNNdroid这个库已经开源在Github上,可以从Github项目页面下载。
关键词
Deep Learning, Deep Convolutional Neural Network (CNN), Mobile GPU, Performance Optimization, Low Energy Con- sumption, Open Source Software, Android, RenderScript
1.介绍
智能手机、可穿戴设备、微型机器人、物联网等越来越多的移动平台都在深度学习的领域找到了相应的应用方向(如图1)。例如在移动设备上,语音识别和图像识别等许多App都受益于机器学习的本地算法。如果允许将模型等数据直接放在客户端,就可以避免和服务器的上下行数据交互而导致的网络延迟等体验的问题。CNN卷积网络在预测的精确性和可扩展性上都取得了很先进的成果,然而像此类密集计算型的网络结构必须依赖硬件级加速才可能在移动设备上得到广泛的应用。
图1:CNN在移动设备上的应用
许多基于深度学习的硬件加速平台都有相应的解决方案了,IBM也正在开发一种用于神经网络的CMOS的芯片,用于在移动设备和物联网设备上。与此同时,类似的解决方案依然处于早期的研发阶段,也并没有商用到现有的移动设备上。
和基于硬件的加速平台不同的是,GPU已经大规模的商用到现在的移动设备上了,同时在软件层面的编码支持也做的非常完善了。利用GPU现成的并行计算能力去实现CNN神经网络在移动端设备上的计算加速是完全可行的。
现存的GPU加速方案的深度学习CNN的开源库有很多种,都是基于服务器和桌面平台的[见附录的6, 7, 8, 9, 10, 11, 12].然而,由于平台架构的差异,简单的把这些开源库移植到移动端上,在某些Case下效果是欠佳的(见2.2节)。目前在移动端上,据我们所知,并没有相应的带有GPU加速的深度学习计算框架的开源库,这些库 [见附录的13, 14, 15, 16]仅仅能够利用移动设备的CPU多核计算能力,而这样局限性很大。
如今,我们提供一个支持GPU加速的开源库,称为“CNNdroid”,可以在Android平台用来通过训练数据集的方式设计和优化CNN的网络。以下是CNNdroid的几个主要亮点。
1. 支持几乎所有的CNN的Layer Type(Section 3.1)
2. 兼容Caffe[6]、Torch[7]、Theano[8]这些开源框架在PC平台、服务器平台上已经训练好的模型(Section 3.2)
3. 现有的Android App可以快速的加入这个库,无需额外的软件依赖(Section 3.3)
4. 开发者可以指定最大的内存消耗(Section 3.4)
5. CNN Layer的GPU和CPU加速均支持(Section 3.5)
6. 自动的硬件条件检测(Section 3.6)
7. 在移动设备上超过60倍的性能提升以及减少130倍的能耗(Section 4)
背景知识以及相关介绍
2.1移动设备的GPU和桌面平台的GPU的区别
现代图形处理单元(GPU)不仅仅能做图形计算,也能够被用来做可编程的通用计算。台式机的GPU长期以来都是可编程的,近期移动设备上的GPU也开放了通用计算的硬件级支持。但受限于GPU的尺寸和功耗,移动GPU和桌面GPU设备还是有很大的差异。
现代移动GPU的Shader Cores(SC)通常成为若干可编程并行计算单元。每个Shader Core都是由若干个ALU并行组成。比如,三星的Exynos 5433芯片是由ARM A53/A57 CPU和Mali T-760 GPU组成(见图2)。T-760 GPU中的每一个SC都具有两个VLIW格式的128位ALU。每个128位ALU能够执行SIMD操作,即并行的两个64位,四个32位或八个16位操作[17]。与桌面平台GPU相比,移动设备的并行ALU架构在并行线程的有效执行中更多地依赖于软件和编译器,而不是动态硬件调度器。
图2: Exynos 5433 mobile processor with ARM A53 / A57 CPU and Mali T-760 GPU
(SC: Shader Core, VLIW: Very Long Instruction Word, SIMD: Single Instruction Multiple Data
更重要的是,在桌面GPU中广泛应用的线程块快速内存共享机制在移动GPU中并不可用,同时许多基于CUDA的桌面平台的Library在移动GPU上也不可以用。
更不幸的是,在软件层面这两端的差异也是巨大的。比如Android提供的RenderScript[18]是一个用于并行计算的库,但是并发线程的机制并不可用。另外,并行线程和并行线程使用的内存中的数据部分必须是一对一的关系。
2.2 CNNdroid 和桌面平台相关库的比较
在服务器和桌面端,已经有很多现成的基于GPU加速的并行计算框架可用于CNN网络,诸如Caffe[6],Torch [7], Theano [8],Tensor- Flow [9], cuDNN [10], cuda-convnet [11],,and Velesnet [12],然而由于两端的硬件和软件的差异,这种加速和并行计算的方法并不能直接的被移植到移动设备上。比如说,Caffe[6]中的卷积操作被展开并转换为矩阵乘法,这些操作对内存的要求比较高,这在移动设备上是不现实的。再举一个例子,Theano [8]中的并行算法虽然与CNNdroid类似,但是在移动GPU中没有使用SIMD单元(详见Section 3.5)。
更不幸的是,桌面的计算库利用桌面GPU和CUDA框架提供的线程管理功能,如快速共享内存和线程同步,这些在移动GPU和Android提供的RenderScript中均不可用。
2.3 CNNdroid和移动平台相关库的比较
在移动设备上,就目前所知的支持CNN深度学习的框架只有[13,14,15,16]。包括了Caffe Mobile[13]和Torch Mobile[14],均受限于多核的CPU计算能力,而只有CNNdroid支持CPU和GPU(详见Section 3.5)。
另外,CNNdroid还兼容Caffe[6]、Torch[7]、和Theano[8]训练出来的CNN模型,方便快速将模型部署到移动设备上(详见Section 3.2)。
开发环境上,不需要安装Android NDK,只需要安装Android SDK即可。
3.CNNdroid库
3.1 CNNLayer Types
CNNDroid库支持几乎大部分的CNN Layers,比如说卷积层,max/mean池化层,全链接层,ReLu(Rectified Linear Units)激活函数,LRN(Local Response Normalization)层,Softmax等。相关的描述和每一层的参数设置在开源库中的文档里有说明[1]。由于库的开源特性,其它的层也可以随时加入。
3.2 模型的准备
模型转换脚本:图3展示了如何将训练好的模型部署到移动端
CNNdroid库提供了一系列的脚本,可以把不同框架训练的库转成CNNdroid格式的模型,目前已经支持Caffe[6],Torch[7],Theano[8],因此可以使用以上框架训练模型然后转为CNNdroid库支持的格式,最终运行在Android移动设备上。当然你也可以模仿这些脚本写出其它平台的转换脚本,CNNdroid使用MessagePack序列化和存储模型中不同层的参数。具体的细节可以参考开源库的说明文档[1]。
图3:CNNdroid的模型部署流程
NetFile:开发者需要准备一个名为NetFile.txt的文本文件,类似于Caffe的.prototxt配置文件,NetFile.txt文件用于配置已经训练好的模型的层次,比如说,CNN Layer的各层的顺序,卷积层中的Padding和Stride的值。图4是一个该文件的样例,更详细的细节可以参考说明文档[1]。
NetFile中也可以配置如下参数,allocated_ram:用于指定本框架可以分配的最大内存上线(见Section 3.4),execution_mode:用于指定是采用并行模式还是串行模式(见Section 3.5),auto_tuning:用于指定auto-tuning是否默认开启(见Section 3.6)。
图4:NetFile示例,如何配置AlexNet[20]的三层网络结构, 以及allocated_ram, execution_mode,auto_tuning参数的配置
3.3模型的执行
一旦将训练好的模型和相应的NetFile文件上传到了移动设备后(图3),这个模型可以被所在的Android App轻易的调用(图5),具体的有如下几个步骤:
第一步,在自己的App中依赖CNNdroid库,CNNdroid库只依赖Android SDK,而不需要安装Android NDK的,也就是说,不依赖其他的第三方库。
第二步,构造RenderScript和CNNdroid对象(图5所示的Steps 2和3)。CNNdroid的构造函数需要提供NetFile文件作为输入,并会自动的创建相应的网络层次。
最后,compute函数负责利用训练好的模型,计算传入的单个图像或者批量图像并返回结果。
图5: 使用CNNdroid库的几个关键调用步骤,
详细的使用方法可以参见开源库中的说明文档 [1].
3.4 内存分配
我们将已经训练好的CNN模型,上传到手机的SD卡上,这些模型中包含了矩阵式的各层参数。在执行每一层前,在compute函数里(图5,step5),相应层的矩阵参数被自动的从SD卡上加载内存里,这会导致大量的内存开销。
为了减少这种内存开销,CNNdroid采用的方法是:保持一部分的层长期驻留在内存中,而其他的层每次都会被创建和销毁。该选择过程开发者无需关心,在CNNdroid构造函数中自动完成(图5,step3)。选择器从最大的层开始,让尽量多的层进入选择器,直到达到NetFile中allocated_ram参数指定的内存上限。
注意:allocated_ram参数不宜设置的过大,比如说,Android 5.0在系统层就会限制每个App的内存上限为512MB。
3.5 加速的方法
在CNNdroid中,不同的层有不同的加速方法。比如数据并行的卷积层和需要大量密集计算的全连接层,就需要用到RenderScript的框架来实现移动端的GPU加速。
这两层的大部分计算可以表示为点积。具体地来说,在卷积层中kernels与input frames进行卷积;而在全连接层中,计算可以表示为矩阵和向量的乘法。在移动设备上使用GPU的SIMD单元可以高效的进行点积的计算。因此,我们分离了大量的向量,并且使用基于RenderScript框架的预定义点积函数来完成运算。也就是说,我们在软件层面体现了这种计算的并行性,而不像是基于CUDA的桌面计算框架库那样把这类问题交给GPU的硬件调度程序。
相对于卷积层和全连接层,其它层的密集型计算相对较少。因此,它们通过多线程并发在多核CPU上进行加速。比较特殊的是,由于ReLU层通常出现在卷积层或全连接层之后,所以把它嵌入到之前的层中,可以在将多个图像传输时提高CNNdroid的性能。
除了上述并行计算的实现之外,CNNdroid还包括所有层的单线程顺序执行的实现。可以通过配置NetFile中的execution_mode参数,指定执行将是顺序模式还是并行模式(图4)。
3.6 自动调整
为了能够在移动设备上达到最好的性能,CNNdroid框架的GPU并行加速算法支持在每个GPU线程上执行自动配额,比如说调配该GPU线程的工作量以及SIMD ALUs的工作量。配额的参数调整决定了并行的粒度。
如果在NetFile(图4)中打开了auto-tuning,那么auto-tuner就会在Android App首次启动时执行。auto-tuner会记录该移动设备上多个预定义的情景下CNN模型的运行时长,用于调整最佳的配额参数。因此,首次启动App需要花费较长的时间。为了公平性以及更清晰的表述我们的实验,在第4节中,我们将关掉auto-tuning。
4.实验评估
我们在三星的Galaxy Note 4和HTC One M9进行了实验。采用的模型是几个标准的CNN网络:LeNet network for MNIST dataset [21],Alex Krizhevsky’s network for CIFAR-10 (Alex’s CIFAR-10) [22], Alex Krizhevsky’s network for ImageNet 2012 dataset (AlexNet) [20].
基准CNN的层设置如图6所示。当移植到CNNdroid格式时,我们还统计了文件大小和内存占用。具体的结果如图7所示。
我们的实验环境是将手机充满电,同时进入飞行模式并且将屏幕亮度调为最低。以下的实验中,并没有每次都从SD卡加载配置和模型,因为在第一次运行时候就加载到内存中了。每次我们都会将16张图片作为输入传给CNNdroid App,接下来测量输出的准确性以及运行耗时和耗电量。
图6: 三种标准的CNN网络的层次
图7: 在CNNdroid格式下使用三种标准CNN网络的文件大小以及内存消耗
4.1准确度
为了测量CNNdroid的准确度,我们同时使用了CNNdroid和Caffe作对比实验。结果显示两者的结果方差是10的-12次方,也就意味着CNNdroid的准确度和Caffe几乎一样。
4.2性能
图8显示了仅使用CPU的线性运行CNN的运行耗时以及使用GPU加速的运行耗时和加快的倍速。报告显示的值是十次运行结果的平均值。
图8:(a)是CNN运行的平均耗时和加速的速率,(b)是整个CNN中最耗时的卷积层的耗时和加速速率
4.3能耗
我们使用“Qualcomm Trepn Profiler”应用程序[25]测量HTC One M9手机基于AlexNet网络结构的每一幅图像的功耗和能耗。
GPU加速执行时,消耗约523 mW功率和0.4 J能量,而仅仅使用CPU执行时消耗2338 mW功率和51.6 J能量。 因此,GPU加速执行消耗的电池消耗减少51.6÷0.4 = 129X。值得注意的是,我们的测量中有大约20%的波动。
5.结论
我们介绍了CNNdroid:一个在Android平台上基于GPU加速CNN网络的开源库。经过实验评估证明该库可以提升60倍速,以及130倍的能耗节省。相关的代码以及说明文档都已经开源并发布在Github上[1]。
6. 相关引用
[1] CNNdroid open source GPU-accelerated library.
https://github.com/ENCP/CNNdroid
[2] Inchul Song, Hyun-Jun Kim, and Paul Barom Jeon. Deep learning for real-time robust facial expression recognition on a smartphone. In IEEE International Conference on Consumer Electronics, pages 564–567, Jan 2014.
[3] Yu-Hsin Chen, Tushar Krishna, Joel Emer, and Vivienne Sze. 14.5 eyeriss: an energy-e cient reconfigurable accelerator for deep convolutional neural networks. In IEEE International Solid-State Circuits Conference, pages 262–263, Jan 2016.
[4] Mohammad Motamedi, Philipp Gysel, Venkatesh Akella, and Soheil Ghiasi. Design space exploration of fpga-based deep convolutional neural networks. In Asia and South Pacific Design Automation Conference, pages 575–580, Jan 2016.
[5] Paul A Merolla, John V Arthur, Rodrigo Alvarez-Icaza, Andrew S Cassidy, Jun Sawada, Filipp Akopyan, Bryan L Jackson, Nabil Imam, Chen Guo, Yutaka Nakamura, Bernard Brezzo, Ivan Vo, Steven K Esser, Rathinakumar Appuswamy, Brian Taba, Arnon Amir, Myron D Flickner, William P Risk, Rajit Manohar, and Dharmendra S Modha. A million spiking-neuron integrated circuit with a scalable communication network and interface. Science, 345(6197):668–673, 2014.
[6] Yangqing Jia, Evan Shelhamer, Jeff Donahue, Sergey Karayev, Jonathan Long, Ross Girshick, Sergio Guadarrama, and Trevor Darrell. Caffe: Convolutional architecture for fast feature embedding. arXiv preprint arXiv:1408.5093, 2014.
[7] Torch. http://torch.ch/ . Accessed 2016-08-01.
[8] James Bergstra, Olivier Breuleux, Fr ́ed ́eric Bastien,
Pascal Lamblin, Razvan Pascanu, Guillaume Desjardins, Joseph Turian, David Warde-Farley, and Yoshua Bengio. Theano: a CPU and GPU math expression compiler. In Proceedings of the Python for Scientific Computing Conference, 2010.
[9] TensorFlow. https://www.tensorflow.org . Accessed 2016-08-01.
[10] Nvidia cuDNN. https://developer.nvidia.com/cudnn . Accessed 2016-08-01.
[11] cuda-convent. https://code.google.com/p/cuda-convnet/ . Accessed 2016-08-01.
[12] Velesnet. https://velesnet.ml/ . Accessed 2016-08-01.
[13] Caffe Android Library.
https://github.com/sh1r0/caffe-android-lib . Accessed 2016-08-01.
[14] Torch-7 for Android.
https://github.com/soumith/torch-android . Accessed 2016-08-01.
[15] A convolutional neural network for the Android
phone. https://github.com/radiodee1/
awesome-cnn-android-python. Accessed 2016-08-01.
[16] Facial attractiveness prediction on Android. https://github.com/eldog/fmobile . Accessed 2016-08-01.
[17] ARM. Mali-T600 Series GPU OpenCL, Version 1.1.0,
Developer Guide. Accessed 2016-08-01.
[18] Android RenderScript Developers Guide.
http://developer.android.com/guide/topics/
renderscript/compute.html. Accessed 2016-08-01.
[19] Messagepack. http://msgpack.org/index.html.
[20] Alex Krizhevsky, Ilya Sutskever, and Geoffrey E.Hinton. Imagenet classification with deep convolutional neural networks. In Advances in Neural Information Processing Systems, 2012.
[21] Y. Lecun, L. Bottou, Y. Bengio, and P. Haffner. Gradient-based learning applied to document recognition. Proceedings of the IEEE, 86(11):2278–2324, Nov 1998.
[22] Alex Krizhevsky. Learning multiple layers of features from tiny images. Technical report, University of Toronto, 2009.
[23] Trepn power profiler. https://developer.qualcomm.com/software/trepn-power-profiler .
本文编译自:CNNdroid: GPU-Accelerated Execution of Trained Deep Convolutional Neural Networks on Android