LiteRT 加速器测试套件 (ATS)

LiteRT 加速器测试套件 (ATS) 是一款综合性工具,用于验证与 LiteRT 框架集成的自定义加速器实现的功能正确性并测量其性能。

概览和核心功能

ATS 的主要功能是针对目标加速器执行预定义的机器学习模型,并将结果与 LiteRT 标准 CPU 后端进行比较。

  • 验证:该套件通过将加速器生成的输出张量(激活)与已知良好的 CPU 后端生成的输出张量进行比较,来执行数值验证。这可确保加速器实现保持所需的精度和正确性。
  • 性能指标:它会自动捕获并记录关键性能详细信息,包括延迟时间和其他相关指标,并向用户提供这些信息。
  • 执行:测试通常在目标设备(例如 Android 手机)上执行,并由 shell 脚本封装容器管理,该容器使用 adb (Android 调试桥) 工具处理文件传输和设置。

测试数据(模型)

ATS 套件使用一系列广泛使用的 .tflite 模型作为其测试数据。输入数据会根据数据类型随机生成,并且可以根据需要进行播种。

包含的型号

系统会自动纳入并下载以下模型以供测试(可能会发生变化):

  • hf_all_minilm_l6_v2
  • hf_mobilevit_small
  • qai_hub_midas
  • qai_hub_real_esrgan_x4plus
  • torchvision_mobilenet_v2
  • torchvision_resnet18
  • torchvision_squeezenet1_1
  • u2net_lite
  • whisper_tiny_decoder
  • whisper_tiny_encoder
  • yamnet
  • yolo11n

手动模型检索

虽然在 bazel run 期间会自动下载模型,但您可以使用 wget 手动检索整个模型集:

wget -p -O <target_file> https://storage.googleapis.com/litert/ats_models.tar.gz

使用 Bazel 定义 ATS 套件

使用 litert_define_ats Bazel 宏来配置和定义特定于其加速器的 ATS 测试目标。

该宏会自动创建 个可运行的目标:

  1. 标准设备端 JIT 测试(用于执行和验证)。
  2. 一个专门的 AOT“仅编译”模式测试(用于主机编译)。

litert_define_ats 用法示例

以下示例为后端名称为 example 的加速器定义了一个名为 example_ats 的 ATS 套件:

# Emits aot-mode and jit-mode test targets, one for running compilation test on host
# and another for running JIT and inference on device
# These targets are named with their respective suffix attribute.
litert_define_ats(
    name = "example_ats",
    backend = "example",
    compile_only_suffix = "_aot",
    do_register = [
        "*mobilenet*",
    ],
    extra_flags = ["--limit=1"],
    jit_suffix = "",
)

执行

如需执行面向 Android 的标准测试(可处理所有 adb 操作),请运行以下命令:

# Handles environment setup, and build + push of library and data dependencies to the device,
# executes the suite on the target.
bazel run -c opt --config=android_arm64 :example_ats

如需执行 AOT 编译测试,请执行以下操作:

# Handle environment setup, and builds library dependencies for host platform.
# Executes the ats compile only flow. The "--compile_mode" flag is already
# bound to the program arguments.
bazel run :example_ats_aot

Linux 执行(主机)

对于在执行 build 的同一台机器上运行 ATS 的 Linux 执行,用户需要直接使用 :ats 二进制文件:

bazel run -c opt :ats

IoT 执行

对于 IoT 执行,用户需要在主机上构建二进制文件,并手动将其推送到设备。

命令行标志

ats 可执行文件接受多个标志,以便对测试和报告进行精细控制。

标志 类型 说明
--backend std::string 必需。要用作被测加速器(“实际”加速器)的 LiteRT 后端。选项为 cpunpugpu
--compile_mode bool 如果为 true,则在工作站上运行 AOT 编译步骤,而不是在设备上执行。注意:此选项会自动绑定到“aot”build 目标,无需显式设置。
--models_out std::string 保存副作用序列化(已编译)模型的目录路径。仅与 AOT 或 JIT 编译相关。
--dispatch_dir std::string 包含加速器调度库的目录的路径(与 NPU 相关)。
--plugin_dir std::string 包含加速器编译器插件库的目录的路径(与 NPU 相关)。
--soc_manufacturer std::string 要针对 AOT 编译的目标 SOC 制造商(与 NPU 编译相关)。
--soc_model std::string 要针对 AOT 编译的目标 SOC 模型(与 NPU 编译相关)。
--iters_per_test size_t 每次测试要运行的迭代次数,每次迭代都使用不同的随机张量数据。
--max_ms_per_test int64_t 在超时之前运行每个测试的最长时间(以毫秒为单位)。
--fail_on_timeout bool 如果执行超时,测试是否应失败。
--csv std::string 用于保存详细报告(采用 CSV 格式)的文件路径。
--dump_report bool 是否将整个报告详细信息直接转储到用户的控制台输出中。
--data_seed std::optional<int> 用于生成全局数据的单个种子。
--do_register std::vector<std::string> 用于明确包含特定测试的正则表达式(例如,*mobilenet*)。
--dont_register std::vector<std::string> 用于排除特定测试的正则表达式。
--extra_models std::vector<std::string> 要添加到测试套件中的目录或模型文件的可选列表。
--limit int32_t 限制注册和运行的测试总数。
--quiet bool 在测试运行期间最大限度地减少日志记录输出。

使用适用于 ATS 的 litert_device_script build 实用程序

ATS 目标用户自动执行包括一个 shell 入口点,该入口点可处理所有环境设置,以及在目标设备与完成 build 的主机(例如 adb push)不同时推送任何必需的库。

此功能通过 litert_device_script 实用程序以通用方式提供,而 ATS build 在后台使用这些实用程序。加速器必须完成注册流程才能访问此 build 功能。除了支持 ats 之外,这些实用程序还可以单独使用,以模拟 cc_binarycc_test(旨在在不同于构建主机且需要推送依赖项的设备上执行)。

后端注册

如需启用新加速器以与 litert_device_script(以及 ATS)搭配使用,必须在 litert_device_common.bzl Bazel 文件中注册其必需的库。注册基于唯一的“后端”名称,该名称会映射到一组可构建或预编译的库,LiteRT 需要这些库才能与相应加速器搭配运行。

注册步骤

  1. 定义 BackendSpec 函数:创建一个函数,用于返回包含新加速器规范的字典。

  2. 指定库 (libs):这是一个元组列表,详细说明了共享库的 Bazel 目标路径以及设备链接器找到该共享库所需的环境变量 (LD_LIBRARY_PATH)。

    • 调度库:运行时执行必需的库。
    • 编译器插件库:AOT 编译模式必需。
  3. 指定库名称(plugindispatch:提供插件库和调度库的文件名。

  4. 注册规范:将新的规范函数合并到主 _Specs 函数中,以便通过其唯一的后端 ID 来使用该函数。

注册示例 (_ExampleSpec)

以下来自 litert_device_common.bzl 的代码展示了如何注册“示例”快捷键:

def _ExampleSpec():
    return {
        # The unique backend ID
        "example": BackendSpec(
            id = "example",
            libs = [
                # Dispatch Library and how to find it on device
                ("//third_party/odml/litert/litert/vendors/examples:libLiteRtDispatch_Example.so", "LD_LIBRARY_PATH"),
                # Compiler Plugin Library
                ("//third_party/odml/litert/litert/vendors/examples:libLiteRtCompilerPlugin_Example.so", "LD_LIBRARY_PATH"),
            ],
            plugin = "libLiteRtCompilerPlugin_Example.so",
            dispatch = "libLiteRtDispatch_Example.so",
        ),
    }

# ... (Other specs are defined here)

def _Specs(name):
    # Your new spec function must be included here
    return (_QualcommSpec() | _GoogleTensorSpec() | _MediatekSpec() | _CpuSpec() | _GpuSpec() | _ExampleSpec())[name]

利用 litert_device_exec 进行注册

注册后,将 litert_device_exec 及相关宏与新的 backend_id 搭配使用。此宏会自动将必需的库和任何指定的数据文件与目标二进制文件捆绑在一起。

cc_binary(
    name = "example_bin",
    srcs = ["example_bin.cc"],
)

litert_device_exec(
    name = "example_bin_device",
    backend_id = "example",  # Uses the libraries registered under "example"
    data = [
        "//third_party/odml/litert/litert/test:testdata/constant_output_tensor.tflite",
    ],
    target = ":example_bin",
)

运行此目标 (bazel run ... :example_bin_device) 将:

  1. 构建 example_bin C++ 二进制文件。
  2. 将二进制文件 libLiteRtDispatch_Example.solibLiteRtCompilerPlugin_Example.so.tflite 文件推送到设备。
  3. 使用 adb shell 执行二进制文件。

设备路径方面的注意事项:设备上文件的规范位置与 Bazel 的 runfile 树(尤其是 /data/local/tmp/runfiles/runfiles_relative_path)相对应。设备脚本会自动处理为动态链接器设置相应路径。

编译模式 (AOT)

对于支持预先 (AOT) 编译步骤的加速器,可以在专用“编译模式”下执行 ATS。

  • 用途:此模式旨在工作站(主机)上运行,而不是在目标设备上运行。它会编译指定目标硬件的模型,但不执行这些模型。
  • 输出:所有已编译的模型都会输出到工作站上的指定目录。
  • 激活:ATS 构建宏将针对 AOT 发出特定目标,其中库是为宿主平台构建的。此流程可在任何带有 --compile_mode 标志的二进制文件中启用,但会自动绑定到 AOT 构建的实参。

未来扩展

除了完整模型之外,该套件还计划扩展为包含针对单个操作 (op) 的专用测试。