TensorFlow团队近日在博客上发布了TensorFlow Lite开发者预览版,据介绍,新的版本可以让模型推理速度提升至原来的4~6倍。
\n以下为博客全文
\n由于设备的处理和能力有限,在移动设备上的计算密集型机器学习模型上运行推理,对资源的要求很高。虽然转换为定点模型是一种加速的方法,但我们的用户已经要求我们提供GPU支持作为加速原始浮点模型推理的选项,且不增加量化的额外复杂性和潜在的准确性损失。
\n我们很高兴地宣布,随着TensorFlow Lite GPU后端开发者预览版的发布,你将能够利用移动GPU来选择模型训练(如下所示),对于不支持的部分,将自动使用CPU进行推理。在未来的几个月里,我们将继续增加额外的操作系统,并改善GPU整体的后端产品。
\n新的后端利用了:
\n- \n
- OpenGL ES 3.1在Android设备上计算着色器\n
- iOS设备上的金属计算着色器\n
今天,我们发布了新的GPU后端的预编译二进制预览版,让开发人员和机器学习研究人员可以尽早尝试这种令人兴奋的新技术。我们计划在2019年晚些时候发布一个完整的开源版本,包含我们从开发者的经验中收集的反馈。
\n目前TensorFlow Lite 仍使用CPU浮点推断进行人脸轮廓检测(非人脸识别)。未来我们会利用新的GPU后端,可以将Pixel 3和三星S9的推理速度提升4~6倍。
\nGPU与CPU性能
\n我们已经在谷歌的产品中进行了几个月新的GPU后端测试,加速了计算密集型网络,为我们的用户提供了重要的用例。
\n对于Pixel 3的人像模式,Tensorflow Lite GPU让前景-背景分割模型的速度提高了4倍以上,新的深度预估模型的推理速度提高了10倍以上,同时还对CPU推理浮点精度提高。在YouTube上的YouTube Stories和Playground Stickers中,实时视频分割模型在各种手机上的测试加速5~10倍。
\n我们发现,对于各种深度神经网络模型,新的GPU后端通常比浮点CPU速度快2~7倍。我们对4个公共模型和2个内部模型进行了基准测试,涵盖了开发人员和研究人员在一系列Android和Apple设备上遇到的常见用例:
\n公共模型:
\n \n(基于移动和嵌入式视觉应用的图像分类模型)
\n \n(图像或视频中估计人体姿势的视觉模型)
\n \n(图像分割模型,将语义标签(如狗、猫、车)分配给输入图像中的每个像素)
\n \n(检测带有边框的多个对象的图像分类模型)
\n谷歌专有用例:
\n1.MLKit
\n2.实时视频分割
\n在更加复杂的神经网络模型上GPU加速效果最显著,这些模型本身更有利于GPU的利用,例如密集的预测/分割或分类任务。在小型模型中,加速效果效果可能略差,但CPU的使用可以降低内存传输固有的延迟成本。
\n如何使用?
\n教程
\n最简单的入门方法是按照我们的教程使用带有GPU委托的TensorFlow Lite演示应用程序。下面简要介绍了这种方法。有关更多信息,请参阅我们的完整文档:https://www.tensorflow.org/lite/performance/gpu_advanced。
\n使用Java for Android
\n我们已经准备了一个完整的Android存档(AAR),包括带有GPU后端的TensorFlow Lite。编辑gradle文件替换当前版本,以包含这个AAR,并将此代码片段添加到Java初始化代码中。
\n// Initialize interpreter with GPU delegate.\nGpuDelegate delegate = new GpuDelegate();\nInterpreter.Options options = (new Interpreter.Options()).addDelegate(delegate);\nInterpreter interpreter = new Interpreter(model, options);\n\n// Run inference.\nwhile (true) {\n writeToInputTensor(inputTensor);\n interpreter.run(inputTensor, outputTensor);\n readFromOutputTensor(outputTensor);\n}\n\n// Clean up.\ndelegate.close();\n\n
\n
使用C ++ for iOS
\n步骤1.下载TensorFlow Lite的二进制版本。
\n步骤2.更改代码,以便在创建模型之后调用ModifyGraphWithDelegate()。
\n// Initialize interpreter with GPU delegate.\nstd::unique_ptr\u0026lt;Interpreter\u0026gt; interpreter;\nInterpreterBuilder(model, op_resolver)(\u0026amp;interpreter);\nauto* delegate = NewGpuDelegate(nullptr); // default config\nif (interpreter-\u0026gt;ModifyGraphWithDelegate(delegate) != kTfLiteOk) return false;\n\n// Run inference.\nwhile (true) {\n WriteToInputTensor(interpreter-\u0026gt;typed_input_tensor\u0026lt;float\u0026gt;(0));\n if (interpreter-\u0026gt;Invoke() != kTfLiteOk) return false;\n ReadFromOutputTensor(interpreter-\u0026gt;typed_output_tensor\u0026lt;float\u0026gt;(0));\n}\n\n// Clean up.\ninterpreter = nullptr;\nDeleteGpuDelegate(delegate);\n\n
\n
如何加速?
\nGPU后端目前支持select操作(请参阅文档)。当只包含这些操作时,你的模型运行速度将最快;不支持的GPU操作将自动退回到CPU进行操作。
\n它是如何工作的?
\n深度神经网络按顺序运行数百个操作,这使得它们非常适合针对吞吐量的并行工作负载而设计的GPU。
\nObjective-C++可通过调用Interpreter::ModifyGraphWithDelegate(),或者通过Interpreter.Options间接调用Interpreter的构造函数来初始化GPU。在初始化阶段,基于从框架接收的执行计划,构建输入神经网络的规范表示。使用此新表示,可应用一组转换规则,包括但不限于:
\n- \n
- 剔除不需要的ops\n
- 将ops替换为性能更好的等效ops\n
- 合并ops,以减少最终生成的着色程序的数量\n
基于此优化图(optimized graph),生成并编译计算着色器。我们目前在Android上使用OpenGL ES 3.1 计算着色器,在iOS上使用Metal 计算着色器。在创建这些计算着色器时,我们还采用了各种特定于体系结构的优化,例如:
\n- \n
- 进行某些操作特殊化而不是较慢的通用实现\n
- 释放寄存器压力\n
- 选择最佳工作组大小\n
- 安全地调整精度\n
- 重新排序显式数学操作\n
在这些优化结束后,编译着色程序可能需要几毫秒到半秒,就像手机游戏一样。一旦着色程序编译完成,新的GPU推理引擎就可以开始工作了。
\n在推断每个输入时:
\n- \n
- 如有必要,输入将移至GPU:如果输入张量还没有存储为GPU内存,那么通过创建GL缓冲区/texture或mtlbuffer(同时还可能复制数据),GPU可以访问输入张量。由于GPU在4通道数据结构中效率最高,因此通道大小不等于4的张量将被重新塑造成更适合GPU的布局。\n
- 执行着色器程序:将上述着色器程序插入命令缓冲区队列中,GPU将这些程序输出。在这一步中,我们还为中间张量管理GPU内存,以尽可能减少后端的内存占用。\n
- 必要时将输出移动到CPU:一旦深度神经网络完成处理,框架就会将结果从GPU内存复制到CPU内存,除非网络的输出可以直接在屏幕上呈现,不需要这样的传输。
\n为了获得最佳体验,我们建议优化输入/输出张量副本和/或网络架构。有关此类优化的详细信息,可以在TensorFlow Lite GPU文档中找到。有关性能最佳实践,请阅读本指南。\n
它有多大?
\nGPU委托将为Android armeabi-v7a APK增加270KB的内存,为iOS增加212KB的内存。但后端是可选的,因此,如果不使用GPU委托,就不需要包含它。
\n未来的工作
\n这只是我们GPU支持工作的开始。除了社区反馈外,我们还打算进行以下改进:
\n- \n
- 扩大运营范围\n
- 进一步优化性能\n
- 发展并最终确定API\n
我们欢迎你在GitHub和StackOverflow页面上留下你的想法和评论。
\n原文链接:
\n \n