深度学习落地移动端——Q音探歌实践(二)

接上文

上一节内容里,我们大致介绍了我们对移动端可用的硬件条件的探索,接下来,我们更专注于介绍一些专注于移动端设备的机器学习框架,以及在Q音探歌,我们接入深度学习服务的一般流程。

4.移动端机器学习框架介绍

深度学习算法推断要在移动端落地,需要着重衡量尺寸和性能的限制,同时又要尽可能的提供给用户较好的体验(推断速度足够快)。Q音探歌倾向使用成熟的机器学习框架快速搭建深度学习服务,我们对比了一些专注于为边缘设备带来高效深度学习的框架,包括NCNN, TensorFlow Lite, Pytorch Mobile 和 FeatherKit。

4.1NCNN

NCNN是腾讯优图开发的高性能神经网络前向计算框架,不仅深刻考虑了手机端的差异性,而且基本实现了卷积神经网络的所有特性,目前已经开源。NCNN从0开始基于C++03标准实现了卷积神经网络的几乎所有功能,它没有依赖任何第三方库(例如BLAS/NNPACK等数学计算库),只使用到了std::vector和std::string两个STL模板,这使得他在精简性上特别突出(默认编译选项下,库体积大约在500K)。代码全部用C/C++编写,通过CMake编译的特点,使得NCNN可以在大多数平台正常运行,例如Android, iOS, linux, MacOS, Windows。支持卷积神经网络,以及多分支多输入的复杂网络结构,如主流的vgg,googlenet, resnet, squeezenet等等。

NCNN为手机端CPU运行做了深度细致的优化,使用ARM NEON指令集实现卷积层,全连接层,池化层等大部分CNN关键层。对于寄存器压力较大的ARM-v7架构,手工编译NEON汇编,内存预对齐,cache预缓存,排列流水线,充分利用一切硬件资源,防止编译器以外负优化。

考虑到手机上内存使用的限制,NCNN在卷积层、全连接层等计算量较大的层实现中, 并没有采用通常框架中的im2col + 矩阵乘法,因为这种方式会构造出非常大的矩阵,消耗大量内存。转而采用原始的滑动窗口卷积实现,并在此基础上进行了优化,大幅节省了内存。在前向网络计算的过程中,NCNN可自动释放中间结果所占用的内存,进一步减少内存占用。

NCNN提供了基于OpenMP的多核心并行计算加速,在多核CPU上启用后能获得很高的加速受益。NCNN提供线程数控制接口,可以针对每个运行实例分别调控,满足不同场景的需求。针对ARM big.LITTLE架构的手机CPU,NCNN提供了更精细的调度控制策略,能够指定大核心还是小核心,或者一起使用,以获得性能和能耗之间的平衡。

NCNN使用自有的模型格式,模型主要储存各层中的权重值。NCNN模型中含有扩展字段,用于兼容不同权重值的储存方式,如常规的单精度浮点型,以及更小的半精度浮点型和8bit量化。大部分深度学习模型都可以采用半精度浮点型减少一半的模型体积,减少APP安装包大小和在线下载模型的耗时。NCNN还带有Caffe转换器,可以把Caffe模型转化为NCNN模型,方便研究成果快速落地。

NCNN还支持直接从内存中加载模型,如果有动态更新模型的需求,这种方法避免了文件IO,效率更高。

NCNN提供了注册自定义层实现的扩展方式,可以将自己实现的特殊层内嵌到NCNN的前向计算过程中,组合出更自由的网络特性和更强大的特性。

总的来说,相比较于Caffe2和TensorFlow Lite,NCNN的计算速度更快,包更小,内存占用更小,但是CPU占用更高也更耗电。

4.2TensorFlow Lite

TensorFlow Lite旨在帮助开发人员在移动或者嵌入式设备上运行TensorFlow模型。为了在边缘上实现机器学习推断,它更突出了低延迟和小尺寸的特点。

TensorFlow Lite由两部分组成:

  • TensorFlow Lite解释器(TensorFlow Lite interpreter),解释器用来在跨平台的边缘设备中执行经过优化的机器学习模型。

  • TensorFlow Lite转换器(TensorFlow Lite converter),转换器用来将TensorFlow模型进行转换,通常会进行一些尺寸和计算速度的优化,以更适于在边缘设备执行。

考虑到边缘设备通常储存空间受限,TensorFlow Lite着重优化了库大小。当支持全部125+种运算符时,TensorFlow Lite的二进制文件约为1MB,当仅需支持常用图像分类模型InceptionV3和MobileNet所需的运算符时,TensorFlow Lite二进制文件约为300KB

概括来说,TensorFlow Lite针对边缘设备的机器学习进行了如下专门设计:

  • 支持了多种平台,包括Android/IOS系统和嵌入式系统

  • 包含多种语言的API接口,例如Java, Swift, Objective-C, C++和Python。

  • 精简了运算符的数量,缩小了尺寸。

  • 支持一些模型优化工具,例如量化,可以在牺牲精度的情况下减小模型尺寸并提高其性能。

4.3Pytorch Mobile – Caffe 2

Caffe是Facebook维护的一款跨平台的深度学习框架,从PyTorch 1.3开始,Caffe2成为PyTorch的一部分。相比较于Caffe1, Caffe2在移动端部署和分布式计算等方面作出了改进,我们可以利用它的跨平台库将模型部署到移动端。

移动端进行的边缘推断主要用于图像和视频处理,为此Caffe2特意增加了一些图像的预处理操作,例如压缩图片、减少通道、归一化处理等等,以加快在移动设备上计算的速度。

为了最大程度地利用有限的计算资源,Caffe2 Runtime集成了两个内部库NNPACK(神经网络包Neural Networks Package)和QNNPACK (量化NNPACK Quantized NNPACK),它们提供卷积和其他重要CNN操作的优化实现,并包含针对移动CPU设计的优化。

Caffe2尤为注重对GPU的利用,得益于Facebook和英伟达的合作,当GPU可用时,Caffe2 可以使用英伟达的CUDA平台,实现高性能、多GPU加速训练和推断。

Caffe2在各种设备上提供了先进的移动深度学习功能,并且已通过Facebook应用程序系列广泛部署。目前,Caffe2已部署到十亿多个设备上,其中约75%基于Android,其余运行iOS。有Facebook在移动端的庞大体量背书,Caffe 2的可靠性和性能都有不错的保证。

4.4FeatherKit

在移动端开发时,经常遇到需要快速验证AI基础能力是否能配合产品玩法的场景。FeatherKit汇总了一些常见到AI视觉能力,例如:人脸识别,手势识别,人体姿态识别等等。支持产品同学对AI能力的脑暴和原型验证。

同时,我们也可以使用其image2Vec模块,通过轻量级的MobileNet V1网络,进行简单的模型部署实现推断计算。

4.5对比

从我们的实验室数据源统计结果来看,对于Android设备而言,NCNN在计算速度,so库大小上取得了一致的优势,它的库文件只有0.7MB,仅相当于TensorFlow Lite的20%,与此同时,它的计算耗时是TensorFlow Lite的50%,这可能与它着重关注精简性以及移动CPU的优化有关。但是,与此同时,它的内存表现和TensorFlow Lite相当,而CPU占用率是后者的4倍,耗电量是后者的1.5倍。FeatherKit则更关注于提供一个快速实现常用AI能力的工具集合,所以它的测试性能并没有特别突出。

对于iOS设备而言,设备和软件的种类少得多,而且Metal使用起来相对简单,更适合把推断放到GPU上执行。从我们的统计数据来看(仅统计了CPU),NCNN在库文件大小上依然保持了优势,只有8.9MB,相当于TensorFlow Lite的13%,但是当仅使用CPU运算时,NCNN仅取得了和后者相当的计算耗时,而CPU占用率是后者的5倍。具体统计数据数据如下图8所示。

图8: Android和iOS端各深度学习框架对比

5.Q音探歌与机器学习

Q音探歌在开发移动端深度学习服务方面做了很多努力。图9说明了机器学习在Q音探歌落地的执行流程,首先利用一系列输入来训练参数化模型,然后将其用于预测。在QQ音乐的数据中心里,我们可以执行大部分学习算法。为了保证训练的可靠性、高效性和高质量性,训练模型阶段通常在服务器中脱机进行。之后,在训练好的模型上进行实时预测的推理阶段可以在服务器中或在移动平台上运行。本文着重于介绍在边缘设备进行实时预测推断。

图9:Q音探歌的机器学习边缘推断的执行流程

5.1在移动端使用机器学习模型与框架

智能手机能够在不依赖于服务器的情况下实现实时的深度学习推断,但也存在局限性。尽管近年来智能手机的计算性能有了显着提高,但这些移动平台还是被各种条件限制,例如功耗,内存和计算性能。不仅如此,如第2节所述,手机芯片的碎片化现象极其严重,这给移动学习带来了机遇,同时也带来了挑战。我们使用开源的机器学习框架,以简化将机器学习带入Q音探歌的任务。

NCNN是一个为手机端极致优化的高性能神经网络前向计算框架。从设计之初深刻考虑手机端的部署和使用。无第三方依赖,跨平台,最惊人的成就是它基于CPU的推断速度非常快(这通常以更高的能耗为代价)。基于NCNN,开发者能够将深度学习算法轻松移植到手机端高效执行,开发出人工智能 APP。

Q音探歌中,通过对拍摄对象的实时推断计算,来推断其对应的MV源。为了提高用户体验,模型必须以2-5 FPS的稳定帧率运行,这对计算速度提出了非常苛刻的要求。这种高性能的算力要求,对于低端设备提出了巨大挑战。为了克服这些挑战,我们在能耗 vs 性能的权衡中,倾向于后者,同时必须建立合适的现场模型,以进行针对性的优化。

5.2移动端边缘推断需要重点设计的方面

与稳定的后台数据中心相比,移动端的性能差异更大,收到的限制也更大。大多数云端推理都在服务器级CPU上运行,其理论计算能力最高可达几个TFLOPS。然而,移动端SoC的能力要低几个数量级,大约在几个GFLOPS到几百GFLOPS之间。为了充分发挥边缘设备的能力进行边缘推理,我们考虑了几个重要的设计原则。

  1. 在移动端从构思到产品部署的迭代通常需要数周的时间,比云端的部署周期要长几个数量级。

    因此,一些重要的现场参数,我们倾向于使用后台配置下发的方式管理,同时以外网的数据变化来驱动我们下一步的优化策略。

  2. 性能是边缘推断的关键。

    因此,性能优化对于移动设备至关重要。

    但是,由于移动生态系统的碎片化,移动设备的性能优化和分析要比云端复杂得多。

    一种简单的方法是针对最小公约数(在这种情况下为移动CPU)开发应用程序。

    这确保s了普遍性和可编程性,同时又提高了效率。

  3. 此外,由于移动端的储存容量一般只有几个GB,压缩模型和代码的大小对于移动设备来说是必不可少的。

    为了减少模型尺寸,通常可以使用权值共享,量化和压缩等技术。

    为了减少so库的尺寸,通常可以剪裁一些不必要的功能,例如剪裁Glog, GFlag,去除反向传播算法等等。

5.3性能、精度、尺寸三者之间的权衡

受限于移动设备广泛的差异性,内存空间、带宽的限制,性能、精度、尺寸三者之间的权衡通常是开发者所面临的重要挑战。

精度是重中之重,但必须附带合理的模型尺寸。神经网络模型的准确性可以直接与用户体验相关联。通常,较大的模型会导致较高的精度,这也是正确的。对于移动设备,在保持模型尺寸合理的同时最大化准确性非常重要。在精度容忍范围内最大程度的减少参数数量,对模型进行量化,通道裁剪等操作。

对于要求实时推断的移动服务,这时减少计算精度带来的主要性能优势在于:(1)减少了用于储存的内存占用;(2)更高的计算效率;(3)减少了带宽限制的影响,例如一些卷积运算。

降低精度的计算对于部分模型体系结构是有益的。但是,当该技术直接应用于所有模型时,我们并没有得到令人满意的时间优化效果。这可能还是受限于系统的能耗管理以及温度控制策略,即使我们降低了精度,在很多低端设备上,仍然无法取得明显的性能提升。

5.4现场建模的必要性

有针对性的性能优化是Q音探歌面临的实际问题。实时性和准确性经常是相互冲突的目标:更高质量的模型需要更长的处理时间,但提供了更高的准确性。如果我们保守地使用一个较小的,计算量较少的模型来满足所有设备,就势必要大幅度的牺牲我们的模型精度。但是,如果我们有更好的方法来预测性能差异,则可以进行更有针对性的优化,同时满足实时性和计算精度的目标,以提供最佳的用户体验(FPS)和服务 (模型精度)。

为了达到设计目标,我们对Q音探歌的服务进行了严格的评估,并使用性能结果来推动更好的解决方案。我们从性能数据中得出的一个主要观察结果是,我们很难通过静态的硬件信息预测出机器学习的推断时间。图10显示了在不同设备上执行矩阵点积乘法的运算耗时与执行神经网络推断的耗时。明显可以看到,对于矩阵点积运算,计算时间y轴是基本符合正态分布的,这说明我们可以通过对机型的建模得到矩阵点积运算时间的预期,但是,神经网络推断的计算时间分布却出现了明显的波动性,虽然高端设备在整体上表现要比中低端设备好的多,但是中端设备的推断性能分布具有很大波动性。

图10:矩阵点积运算耗时和神经网络推断计算耗时在不同设备上的表现

智能手机上的推理性能是不确定的,并且波动很大。这当然是我们不希望看到的,因为不确定的推理时间直接影响用户体验。如果我们能够对可变的性能进行建模和预测,则可以进行针对性的设计来进行优化,以根据情况选择最优方案。推断现场的性能评估是我们迭代模型微调过程的重要参考。

我们通过在内部实验室内搭建了一些推理模型来学习推断手机的性能,尽管我们看到了模型中的参数和性能有一定关系,但是相关性不那么明显。这是一个挑战,因为理想情况下,我们希望模型能够准确的预知设备的推断性能。从我们的观察来看,这项工作似乎是不切实际的。

生产环境中存在更大的性能差异,其原因可能是部署的智能手机和智能手机所处的环境(例如,环境温度或用户允许同时运行的应用程序数量)所导致的。并发的流程或后台活动导致资源争用,从而导致性能扰动。此外,移动处理器的性能不仅受处理器结点温度的限制,还受到智能手机表面温度的符合人体工程学要求的限制。这意味着,根据智能手机的使用方式和使用地点,在生产环境中触发热节流的可能性可能会更高,这代表了更现实的使用场景。最后,工艺差异和电池老化也会导致性能差异。为了获得有代表性的性能优化方案,在移动设备中进行性能评估的现场研究非常重要。

对移动设备的性能评估的现场研究可以指导我们进行一些重要优化策略。例如,移动端进行的边缘推断主要用于图像和视频处理,这时,对图象的进行预处理操作就非常重要了,为了加快推断速度,我们可以使用压缩图片、减少通道、归一化处理等操作,很明显,这些操作势必会影响到模型的识别精度,何时使用这些优化策略,就有赖于我们的现场研究。

总而言之,在移动推断中观察到的显着性能差异引入了不同的用户体验。如果采用经典方法对机器学习模型的性能和能耗进行建模和评估,则设计人员将冒着用户体验差异巨大的风险进行交付。因此,对于移动推断设计而言,针对性能进行差异化设计十分重要。常规的利用实验测量平均值,最大值,最小值和标准差,用来评估结果(例如,推理时间性能)也是有意义的,一般这些数据可以用来纵向对比,帮助我们对比旧版本的性能。不过,更重要的是,我们要重视现场研究对于移动端机器学习设计的作用。

5.5一个识别MV的例子

识别MV面临的挑战是处理实时推断的巨大计算量。为了在运行Q音探歌的移动平台上启用这一功能,我们训练了特定于移动设备的模型,并执行了量化,同时我们在选取移动端学习框架时,倾向于选择推断速度更快的NCNN框架。

首先,QQ音乐数据中心会利用后台的MV数据构建参数化模型,在经过深度学习的训练之后,我们得到初步的模型,为了在移动终端使用这些模型,我们还需要进行了一些技术优化,例如量化,这时,我们需要权衡精度和性能两者的关系。经过模型训练和评估后,下一步是导出和发布模型,交由移动端开发负责集成移动端深度学习框架以及模型。考虑到移动端的复杂情况,我们针对识别现场进行了建模分类,例如当前的晃动情况、上次推断时间等等,来决定我们是否对图象的进行压缩图片、减少通道等等预处理操作。

6.总结

在应用中部署深度学习的服务需求日益增加,带来了许多激动人心的机遇,但在边缘设备上却出现了各种复杂的设计挑战。本文介绍了在边缘实现机器学习推断的生产实践。我们首先采用数据驱动的方法,介绍了智能手机领域的软/硬件异构性现状,这决定了深度学习应用程序开发的设计方案。尽管本文展示了在客户端深度学习推理的可能性,但我们指出了现场研究的重要性,要着重关注生产环境中的性能差异效应。我们希望本文提供的观察、见解和我们针对不同平台的设计原则能够帮助大家更好地设计和评估移动端的深度学习推断。

6.1大多数Android移动推理都在CPU上运行

考虑到协处理器或者GPU上进行推断的困难,有点违反直觉的是,目前在Android设备上的推断几乎都是在移动CPU上进行处理的。

目前,大多数推断都在比较老旧的CPU架构上运行。面向未来的研究当然很重要,但现实情况是,大量的智能手机存货尚未完成迭代,这需要时间。这不仅是存量市场的情况,这些智能手机的很大一部分是在最近一到两年内出售的,这可能是由于消费市场导向造成的,存在高中低端的市场区分。

尽管目前的统计数据显示绝大多数推断都在CPU上运行, 但是,如果看一下趋势,就会发现越来越多的设备将会支持NPU和诸如NN API之类的可编程接口。此外,在DSP或者GPU上运行,我们可以最大程度的降低功耗,获得更稳定的推断时间,所以CPU应该不会是未来移动推断的最佳载体。但是,仅当可编程性和整个系统堆栈都完善的时候,协处理器的性能优势才会体现。

6.2移动CPU和GPU之间的性能差异不是100倍

考虑到服务器CPU和GPU之间的性能差距通常为60至100倍,人们可能会怀疑在移动端也发现了类似的趋势。然而,这种情况并非如此。大部分移动GPU的速度都比移动CPU快15倍以下。这在很大程度上是因为移动GPU并非旨在处理与离散GPU相同级别的高分辨率图形渲染,其主要功能是帮助在相对低端的环境中加载图像。

6.3可编程性是使用移动协处理器/加速器的主要障碍

使用GPU和DSP的主要挑战之一是可编程性。对于Android智能手机,搭载OpenCL并没有成为统一的规范。苹果设备做的更好,部分原因是设备和软件的种类少得多。Metal也起了很重要的作用,因为它使用起来相对简单。因此,许多iPhone推断都在移动GPU上运行。随着Vulkan和DSP工程技术的推出,推理正在进入协处理器。展望未来,要使现有的移动GPU和DSP硬件更适合于处理机器学习推断,需要进行更多的研究和工程工作,这将会对边缘机器学习产生重大影响。

6.4性能差异是一个重要挑战

在移动端落地机器学习推断,一个不容忽视的问题是性能可变性,这对实时和面向用户的系统是很大挑战。快速推断在边缘推断中是非常重要的一环,针对平均情况的优化设计事实上只能在一小部分用户中生效,而针对所有移动设备的设计则意味着保守的设计决策。对于移动推理而言,最重要的是要在考虑性能分布的情况下能推测出当前的性能水平。