TensorFlow Lite 代理

简介

代理通过利用设备上的加速器(如 GPU 和 数字信号处理器 (DSP))来实现 TensorFlow Lite 模型的硬件加速。

默认情况下,TensorFlow Lite 使用针对 ARM Neon 指令集优化的 CPU 内核。但是,CPU 是一种多用途处理器,不一定针对机器学习模型中常见的繁重算术运算(例如,卷积和密集层中涉及的矩阵数学)进行优化。

另一方面,大多数现代移动电话都包含更适合处理这些繁重运算的芯片。将它们用于神经网络运算在延迟和能效方面提供了巨大的优势。例如,GPU 可以将延迟提高 5 倍,而 Qualcomm® Hexagon DSP 在我们的实验中已证明可以将功耗降低高达 75%。

这些加速器中的每一个都具有相关的 API,这些 API 允许自定义计算,例如 OpenCLOpenGL ES 用于移动 GPU,以及 Qualcomm® Hexagon SDK 用于 DSP。通常,您需要编写大量自定义代码才能通过这些接口运行神经网络。当您考虑到每个加速器都有其优缺点,并且不能执行神经网络中的所有操作时,事情会变得更加复杂。TensorFlow Lite 的代理 API 通过充当 TFLite 运行时和这些底层 API 之间的桥梁来解决此问题。

runtime with delegates

选择代理

TensorFlow Lite 支持多个代理,每个代理都针对特定平台和特定类型的模型进行了优化。通常,将有多个代理适用于您的用例,具体取决于两个主要标准:您所针对的平台(Android 或 iOS?)以及您尝试加速的模型类型(浮点型或量化型?)。

按平台划分的代理

跨平台(Android 和 iOS)

  • GPU 代理 - GPU 代理可在 Android 和 iOS 上使用。它针对运行 32 位和 16 位浮点型模型(在有 GPU 的情况下)进行了优化。它还支持 8 位量化模型,并在 GPU 上提供与其浮点型版本相当的性能。有关 GPU 代理的详细信息,请参阅 TensorFlow Lite on GPU。有关使用 GPU 代理与 Android 和 iOS 的分步教程,请参阅 TensorFlow Lite GPU 代理教程

Android

  • 适用于较新 Android 设备的 NNAPI 代理 - NNAPI 代理可用于加速在具有 GPU、DSP 和/或 NPU 的 Android 设备上运行的模型。它在 Android 8.1 (API 27+) 或更高版本中可用。有关 NNAPI 代理的概述、分步说明和最佳实践,请参阅 TensorFlow Lite NNAPI 代理
  • 针对旧版 Android 设备的六边形委托 - 六边形委托可用于在配备高通六边形 DSP 的 Android 设备上加速模型。它可用于运行旧版 Android 的设备,这些设备不支持 NNAPI。有关更多详细信息,请参阅 TensorFlow Lite 六边形委托

iOS

  • 针对新款 iPhone 和 iPad 的 Core ML 委托 - 对于配备神经引擎的新款 iPhone 和 iPad,您可以使用 Core ML 委托来加速 32 位或 16 位浮点模型的推理。神经引擎适用于配备 A12 SoC 或更高版本的 Apple 移动设备。有关 Core ML 委托的概述和分步说明,请参阅 TensorFlow Lite Core ML 委托

按模型类型划分的委托

每个加速器都是针对特定数据位宽设计的。如果您向仅支持 8 位量化操作的委托(例如 六边形委托)提供浮点模型,它将拒绝所有操作,模型将完全在 CPU 上运行。为了避免此类意外情况,下表提供了基于模型类型的委托支持概述

模型类型 GPU NNAPI 六边形 CoreML
浮点(32 位)
训练后 float16 量化
训练后动态范围量化
训练后整数量化
量化感知训练

验证性能

本节中的信息可作为缩短可能改进应用程序的委托列表的粗略指南。但是,重要的是要注意,每个委托都有一组预定义的操作,并且其性能可能因模型和设备而异;例如,NNAPI 委托可能会选择在 Pixel 手机上使用 Google 的 Edge-TPU,而在另一台设备上使用 DSP。因此,通常建议您进行一些基准测试,以衡量委托对您的需求是否有用。这也有助于证明将委托附加到 TensorFlow Lite 运行时所带来的二进制大小增加的合理性。

TensorFlow Lite 拥有广泛的性能和准确性评估工具,可以帮助开发人员自信地在应用程序中使用委托。这些工具将在下一节中讨论。

评估工具

延迟和内存占用

TensorFlow Lite 的 基准测试工具 可以与合适的参数一起使用,以估计模型性能,包括平均推理延迟、初始化开销、内存占用等。此工具支持多个标志,以找出模型的最佳委托配置。例如,--gpu_backend=gl 可以与 --use_gpu 一起指定,以测量使用 OpenGL 的 GPU 执行。支持的委托参数的完整列表在 详细文档 中定义。

以下是一个使用 adb 通过 GPU 运行量化模型的示例

adb shell /data/local/tmp/benchmark_model \
  --graph=/data/local/tmp/mobilenet_v1_224_quant.tflite \
  --use_gpu=true

您可以从 此处 下载此工具的预构建版本(适用于 Android,64 位 ARM 架构)(更多详细信息)。

准确性和正确性

委托通常以与 CPU 对应部分不同的精度执行计算。因此,使用委托进行硬件加速会带来(通常很小的)精度权衡。请注意,这并非始终如此;例如,由于 GPU 使用浮点精度来运行量化模型,因此可能会略微提高精度(例如,在 ILSVRC 图像分类中提高 <1% 的 Top-5 精度)。

TensorFlow Lite 有两种类型的工具来衡量委托在给定模型上的行为准确性:基于任务与任务无关。本节中描述的所有工具都支持 高级委托参数,这些参数由上一节中的基准测试工具使用。请注意,以下小节侧重于委托评估(委托的执行是否与 CPU 相同?),而不是模型评估(模型本身是否适合该任务?)。

基于任务的评估

TensorFlow Lite 拥有工具来评估两个基于图像的任务的正确性

这些工具的预构建二进制文件(Android,64 位 ARM 架构)以及文档可以从以下位置找到

以下示例演示了使用 NNAPI 在 Pixel 4 上利用 Google 的 Edge-TPU 进行 图像分类评估

adb shell /data/local/tmp/run_eval \
  --model_file=/data/local/tmp/mobilenet_quant_v1_224.tflite \
  --ground_truth_images_path=/data/local/tmp/ilsvrc_images \
  --ground_truth_labels=/data/local/tmp/ilsvrc_validation_labels.txt \
  --model_output_labels=/data/local/tmp/model_output_labels.txt \
  --output_file_path=/data/local/tmp/accuracy_output.txt \
  --num_images=0 # Run on all images. \
  --use_nnapi=true \
  --nnapi_accelerator_name=google-edgetpu

预期输出是 Top-K 指标列表(从 1 到 10)

Top-1 Accuracy: 0.733333
Top-2 Accuracy: 0.826667
Top-3 Accuracy: 0.856667
Top-4 Accuracy: 0.87
Top-5 Accuracy: 0.89
Top-6 Accuracy: 0.903333
Top-7 Accuracy: 0.906667
Top-8 Accuracy: 0.913333
Top-9 Accuracy: 0.92
Top-10 Accuracy: 0.923333

与任务无关的评估

对于没有既定设备上评估工具的任务,或者如果您正在尝试使用自定义模型,TensorFlow Lite 拥有 推理差异 工具。(Android,64 位 ARM 二进制架构二进制文件 此处

推理差异比较 TensorFlow Lite 在两种设置下的执行情况(在延迟和输出值偏差方面)

  • 单线程 CPU 推理
  • 用户定义的推理 - 由 这些参数 定义

为此,该工具会生成随机高斯数据,并将其传递给两个 TFLite 解释器 - 一个运行单线程 CPU 内核,另一个由用户的参数进行参数化。

它会测量两者的延迟,以及每个解释器输出张量之间的绝对差异(按元素计算)。

对于具有单个输出张量的模型,输出可能如下所示

Num evaluation runs: 50
Reference run latency: avg=84364.2(us), std_dev=12525(us)
Test run latency: avg=7281.64(us), std_dev=2089(us)
OutputDiff[0]: avg_error=1.96277e-05, std_dev=6.95767e-06

这意味着对于索引为 0 的输出张量,CPU 输出中的元素与委托输出中的元素平均相差 1.96e-05

请注意,解释这些数字需要更深入地了解模型以及每个输出张量所代表的含义。如果它是一个简单的回归,用于确定某种分数或嵌入,则差异应该很小(否则就是委托的错误)。但是,像 SSD 模型中的“检测类别”这样的输出更难解释。例如,它可能会使用此工具显示差异,但这并不一定意味着委托存在真正的问题:考虑两个(虚构的)类别:“电视(ID:10)”,“显示器(ID:20)” - 如果委托略微偏离黄金真理,并显示显示器而不是电视,则此张量的输出差异可能高达 20-10 = 10。