LiteRT 的 GPU 代理

使用图形处理单元 (GPU) 运行机器学习 (ML) 模型 可以显著提升模型的性能和用户体验 支持机器学习的应用。LiteRT 支持使用 GPU 和 其他专用处理器通过称为 受托人。允许将 GPU 与 LiteRT ML 搭配使用 可以带来以下好处:

  • 速度 - GPU 专为大规模并行的高吞吐量而打造 工作负载这种设计使其非常适合深度神经网络, 由大量运算符组成,每个运算符处理输入张量, 可以并行处理,这通常可以缩短延迟时间。在 最佳方案是,在 GPU 上运行模型可能足够快, 实时应用场景,这是以前无法实现的。
  • 能效 - GPU 以非常高效的 和优化方式,通常耗电量较低 与在 CPU 上运行的相同任务相比,

本文档简要介绍了 LiteRT 对 GPU 的支持,以及 介绍 GPU 处理器的高级用法如需详细了解 在特定平台上实现 GPU 支持,请参阅以下指南:

GPU ML 操作支持

对于可以执行的 TensorFlow ML 操作(简称“操作”)存在一些限制 由 LiteRT GPU 代理加速处理。代理支持 以下操作(采用 16 位和 32 位浮点精度):

  • ADD
  • AVERAGE_POOL_2D
  • CONCATENATION
  • CONV_2D
  • DEPTHWISE_CONV_2D v1-2
  • EXP
  • FULLY_CONNECTED
  • LOGICAL_AND
  • LOGISTIC
  • LSTM v2 (Basic LSTM only)
  • MAX_POOL_2D
  • MAXIMUM
  • MINIMUM
  • MUL
  • PAD
  • PRELU
  • RELU
  • RELU6
  • RESHAPE
  • RESIZE_BILINEAR v1-3
  • SOFTMAX
  • STRIDED_SLICE
  • SUB
  • TRANSPOSE_CONV

默认情况下,只有版本 1 支持所有操作。启用量化 support 启用相应的版本,例如 ADD v2。

排查 GPU 支持问题

如果某些操作不受 GPU 代理支持,框架将 仅在 GPU 上运行图表的一部分,在 CPU 上运行其余部分。到期日 会降低 CPU/GPU 同步的高成本,像这样的拆分执行模式 通常会导致性能低于在 只使用 CPU。在这种情况下,应用会生成警告,例如:

WARNING: op code #42 cannot be handled by this delegate.

此类型的失败没有回调,因为这不是实际的 运行时失败。使用 GPU 代理测试模型的执行情况时, 您应留意这些警告。如果出现大量此类警告, 这表明您的模型并不适合用于 GPU 加速; 可能需要重构模型。

示例模型

以下示例模型旨在利用 GPU 加速 LiteRT 供您参考和测试:

针对 GPU 进行优化

以下技巧可以帮助您在运行模型时获得更好的性能 在 GPU 硬件上使用 LiteRT GPU 代理:

  • 重塑操作 - 某些在 CPU 上快速完成的操作 因为移动设备上的 GPU 成本较高。重塑操作在 运行成本高昂,包括 BATCH_TO_SPACESPACE_TO_BATCHSPACE_TO_DEPTH 等。您应该仔细研究如何使用变形 操作,并考虑可能仅适用于探索数据的 或早期的模型迭代。移除它们可能会显著改善 提高性能。

  • 图片数据通道 - 在 GPU 上,张量数据分为 4 个通道,以及 因此,对形状为 [B,H,W,5] 的张量执行计算 在形状为 [B,H,W,8] 的张量上没什么变化,但明显 [B,H,W,4]。如果您使用的相机硬件支持 RGBA,馈送四通道输入的速度明显更快,因为它可以避免 从三通道 RGB 到四通道 RGBX 的内存副本。

  • 针对移动设备进行了优化的模型 - 为了获得最佳效果,您应该考虑 使用针对移动设备进行了优化的网络架构重新训练分类器。 针对设备端推断进行优化可以显著缩短延迟时间并 利用移动硬件功能降低功耗

高级 GPU 支持

您可以结合使用其他高级技术与 GPU 处理, 提升模型性能,包括量化和序列化。 以下部分更详细地介绍了这些方法。

使用量化模型

本部分介绍 GPU 委托如何加速 8 位量化模型, 包括:

为了优化性能,请使用同时支持浮点输入和 输出张量。

具体是怎么运作的?

由于 GPU 后端仅支持浮点执行,因此我们运行 为其提供原始模型的“浮点视图”。在 这涉及以下步骤:

  • 常量张量(例如权重/偏差)会被去量化到 GPU 内存。为受托人启用受托服务时, LiteRT。

  • GPU 程序的输入和输出(如果经过 8 位量化)为 反量化和量化(分别)进行推断。此操作 是利用 LiteRT 的优化内核在 CPU 上完成的。

  • 在运算之间插入量化模拟器以模拟量化模拟器 行为对于操作期望激活操作的模型而言,这种方法是必不可少的 遵循量化期间学习到的边界。

有关通过 GPU 委托启用此功能的信息,请参阅 以下:

通过序列化缩短初始化时间

借助 GPU 代理功能,您可以从预编译的内核代码加载并加载 序列化并保存在磁盘上的模型数据。这种方法可以避免 可减少高达 90% 的启动时间。这项改进 可通过交换磁盘空间来节省时间来实现。您可以启用此功能 其中包含几个配置选项,如以下代码示例所示:

C++

    TfLiteGpuDelegateOptionsV2 options = TfLiteGpuDelegateOptionsV2Default();
    options.experimental_flags |= TFLITE_GPU_EXPERIMENTAL_FLAGS_ENABLE_SERIALIZATION;
    options.serialization_dir = kTmpDir;
    options.model_token = kModelToken;

    auto* delegate = TfLiteGpuDelegateV2Create(options);
    if (interpreter->ModifyGraphWithDelegate(delegate) != kTfLiteOk) return false;
      

Java

    GpuDelegate delegate = new GpuDelegate(
      new GpuDelegate.Options().setSerializationParams(
        /* serializationDir= */ serializationDir,
        /* modelToken= */ modelToken));

    Interpreter.Options options = (new Interpreter.Options()).addDelegate(delegate);
      

使用序列化功能时,请确保您的代码符合以下要求 实现规则:

  • 将序列化数据存储在其他组织无法访问的目录中 。在 Android 设备上,请使用 getCodeCacheDir() 指向当前应用专用的位置。
  • 对于特定型号的设备,模型令牌必须是唯一的。您可以 根据模型数据生成指纹,并使用 例如 farmhash::Fingerprint64