Cómo reducir el tamaño de los objetos binarios de LiteRT

Descripción general

Cuando implementas modelos para aplicaciones de aprendizaje automático en el dispositivo (ODML), es importante tener en cuenta la memoria limitada disponible en los dispositivos móviles. Los tamaños de los archivos binarios del modelo se correlacionan estrechamente con la cantidad de operaciones que se usan en el modelo. LiteRT te permite reducir el tamaño de los archivos binarios del modelo con compilaciones selectivas. Las compilaciones selectivas omiten las operaciones no utilizadas en tu conjunto de modelos y producen una biblioteca compacta con solo el tiempo de ejecución y los kernels de operaciones necesarios para que el modelo se ejecute en tu dispositivo móvil.

La compilación selectiva se aplica a las siguientes tres bibliotecas de operaciones.

  1. Biblioteca de operaciones integrada en LiteRT
  2. Operaciones personalizadas de LiteRT
  3. Selecciona la biblioteca de operaciones de TensorFlow

En la siguiente tabla, se muestra el impacto de las compilaciones selectivas para algunos casos de uso comunes:

Nombre del modelo Dominio Arquitectura de destino Tamaños de los archivos AAR
Mobilenet_1.0_224(float) Clasificación de imágenes armeabi-v7a tensorflow-lite.aar (296,635 bytes)
arm64-v8a tensorflow-lite.aar (382,892 bytes)
SPICE Extracción del tono del sonido armeabi-v7a tensorflow-lite.aar (375,813 bytes)
tensorflow-lite-select-tf-ops.aar (1,676,380 bytes)
arm64-v8a tensorflow-lite.aar (421,826 bytes)
tensorflow-lite-select-tf-ops.aar (2,298,630 bytes)
i3d-kinetics-400 Clasificación de videos armeabi-v7a tensorflow-lite.aar (240,085 bytes)
tensorflow-lite-select-tf-ops.aar (1,708,597 bytes)
arm64-v8a tensorflow-lite.aar (273,713 bytes)
tensorflow-lite-select-tf-ops.aar (2,339,697 bytes)

Compila LiteRT de forma selectiva con Bazel

En esta sección, se supone que descargaste los códigos fuente de TensorFlow y configuraste el entorno de desarrollo local para Bazel.

Cómo compilar archivos AAR para el proyecto de Android

Para compilar los archivos AAR de LiteRT personalizados, proporciona las rutas de acceso a los archivos de tu modelo de la siguiente manera.

sh tensorflow/lite/tools/build_aar.sh \
  --input_models=/a/b/model_one.tflite,/c/d/model_two.tflite \
  --target_archs=x86,x86_64,arm64-v8a,armeabi-v7a

El comando anterior generará el archivo AAR bazel-bin/tmp/tensorflow-lite.aar para las operaciones integradas y personalizadas de LiteRT y, de manera opcional, generará el archivo AAR bazel-bin/tmp/tensorflow-lite-select-tf-ops.aar si tus modelos contienen operaciones de Select TensorFlow. Ten en cuenta que esto compila un AAR "grueso" con varias arquitecturas diferentes. Si no las necesitas todas, usa el subconjunto adecuado para tu entorno de implementación.

Compila con operaciones personalizadas

Si desarrollaste modelos de LiteRT con operaciones personalizadas, puedes compilarlos agregando las siguientes marcas al comando de compilación:

sh tensorflow/lite/tools/build_aar.sh \
  --input_models=/a/b/model_one.tflite,/c/d/model_two.tflite \
  --target_archs=x86,x86_64,arm64-v8a,armeabi-v7a \
  --tflite_custom_ops_srcs=/e/f/file1.cc,/g/h/file2.h \
  --tflite_custom_ops_deps=dep1,dep2

La marca tflite_custom_ops_srcs contiene los archivos fuente de tus operaciones personalizadas, y la marca tflite_custom_ops_deps contiene las dependencias para compilar esos archivos fuente. Ten en cuenta que estas dependencias deben existir en el repo de TensorFlow.

Usos avanzados: Reglas personalizadas de Bazel

Si tu proyecto usa Bazel y deseas definir dependencias personalizadas de TFLite para un conjunto determinado de modelos, puedes definir las siguientes reglas en el repositorio de tu proyecto:

Para los modelos que solo tienen operaciones integradas, haz lo siguiente:

load(
    "@org_tensorflow//tensorflow/lite:build_def.bzl",
    "tflite_custom_android_library",
    "tflite_custom_c_library",
    "tflite_custom_cc_library",
)

# A selectively built TFLite Android library.
tflite_custom_android_library(
    name = "selectively_built_android_lib",
    models = [
        ":model_one.tflite",
        ":model_two.tflite",
    ],
)

# A selectively built TFLite C library.
tflite_custom_c_library(
    name = "selectively_built_c_lib",
    models = [
        ":model_one.tflite",
        ":model_two.tflite",
    ],
)

# A selectively built TFLite C++ library.
tflite_custom_cc_library(
    name = "selectively_built_cc_lib",
    models = [
        ":model_one.tflite",
        ":model_two.tflite",
    ],
)

Para los modelos con la opción Select TF ops, haz lo siguiente:

load(
    "@org_tensorflow//tensorflow/lite/delegates/flex:build_def.bzl",
    "tflite_flex_android_library",
    "tflite_flex_cc_library",
)

# A Select TF ops enabled selectively built TFLite Android library.
tflite_flex_android_library(
    name = "selective_built_tflite_flex_android_lib",
    models = [
        ":model_one.tflite",
        ":model_two.tflite",
    ],
)

# A Select TF ops enabled selectively built TFLite C++ library.
tflite_flex_cc_library(
    name = "selective_built_tflite_flex_cc_lib",
    models = [
        ":model_one.tflite",
        ":model_two.tflite",
    ],
)

Usos avanzados: Compila bibliotecas compartidas personalizadas de C/C++

Si deseas compilar tus propios objetos compartidos personalizados de C/C++ de TFLite para los modelos determinados, puedes seguir los pasos que se indican a continuación:

Crea un archivo BUILD temporal ejecutando el siguiente comando en el directorio raíz del código fuente de TensorFlow:

mkdir -p tmp && touch tmp/BUILD

Cómo compilar objetos compartidos personalizados en C

Si deseas compilar un objeto compartido de C de TFLite personalizado, agrega lo siguiente al archivo tmp/BUILD:

load(
    "//tensorflow/lite:build_def.bzl",
    "tflite_custom_c_library",
    "tflite_cc_shared_object",
)

tflite_custom_c_library(
    name = "selectively_built_c_lib",
    models = [
        ":model_one.tflite",
        ":model_two.tflite",
    ],
)

# Generates a platform-specific shared library containing the LiteRT C
# API implementation as define in `c_api.h`. The exact output library name
# is platform dependent:
#   - Linux/Android: `libtensorflowlite_c.so`
#   - Mac: `libtensorflowlite_c.dylib`
#   - Windows: `tensorflowlite_c.dll`
tflite_cc_shared_object(
    name = "tensorflowlite_c",
    linkopts = select({
        "//tensorflow:ios": [
            "-Wl,-exported_symbols_list,$(location //tensorflow/lite/c:exported_symbols.lds)",
        ],
        "//tensorflow:macos": [
            "-Wl,-exported_symbols_list,$(location //tensorflow/lite/c:exported_symbols.lds)",
        ],
        "//tensorflow:windows": [],
        "//conditions:default": [
            "-z defs",
            "-Wl,--version-script,$(location //tensorflow/lite/c:version_script.lds)",
        ],
    }),
    per_os_targets = True,
    deps = [
        ":selectively_built_c_lib",
        "//tensorflow/lite/c:exported_symbols.lds",
        "//tensorflow/lite/c:version_script.lds",
    ],
)

El destino recién agregado se puede compilar de la siguiente manera:

bazel build -c opt --cxxopt=--std=c++17 \
  //tmp:tensorflowlite_c

y para Android (reemplaza android_arm por android_arm64 para 64 bits):

bazel build -c opt --cxxopt=--std=c++17 --config=android_arm \
  //tmp:tensorflowlite_c

Cómo compilar objetos compartidos personalizados de C++

Si deseas compilar un objeto compartido de C++ de TFLite personalizado, agrega lo siguiente al archivo tmp/BUILD:

load(
    "//tensorflow/lite:build_def.bzl",
    "tflite_custom_cc_library",
    "tflite_cc_shared_object",
)

tflite_custom_cc_library(
    name = "selectively_built_cc_lib",
    models = [
        ":model_one.tflite",
        ":model_two.tflite",
    ],
)

# Shared lib target for convenience, pulls in the core runtime and builtin ops.
# Note: This target is not yet finalized, and the exact set of exported (C/C++)
# APIs is subject to change. The output library name is platform dependent:
#   - Linux/Android: `libtensorflowlite.so`
#   - Mac: `libtensorflowlite.dylib`
#   - Windows: `tensorflowlite.dll`
tflite_cc_shared_object(
    name = "tensorflowlite",
    # Until we have more granular symbol export for the C++ API on Windows,
    # export all symbols.
    features = ["windows_export_all_symbols"],
    linkopts = select({
        "//tensorflow:macos": [
            "-Wl,-exported_symbols_list,$(location //tensorflow/lite:tflite_exported_symbols.lds)",
        ],
        "//tensorflow:windows": [],
        "//conditions:default": [
            "-Wl,-z,defs",
            "-Wl,--version-script,$(location //tensorflow/lite:tflite_version_script.lds)",
        ],
    }),
    per_os_targets = True,
    deps = [
        ":selectively_built_cc_lib",
        "//tensorflow/lite:tflite_exported_symbols.lds",
        "//tensorflow/lite:tflite_version_script.lds",
    ],
)

El destino recién agregado se puede compilar de la siguiente manera:

bazel build -c opt  --cxxopt=--std=c++17 \
  //tmp:tensorflowlite

y para Android (reemplaza android_arm por android_arm64 para 64 bits):

bazel build -c opt --cxxopt=--std=c++17 --config=android_arm \
  //tmp:tensorflowlite

Para los modelos con la opción Select TF ops, también debes compilar la siguiente biblioteca compartida:

load(
    "@org_tensorflow//tensorflow/lite/delegates/flex:build_def.bzl",
    "tflite_flex_shared_library"
)

# Shared lib target for convenience, pulls in the standard set of TensorFlow
# ops and kernels. The output library name is platform dependent:
#   - Linux/Android: `libtensorflowlite_flex.so`
#   - Mac: `libtensorflowlite_flex.dylib`
#   - Windows: `libtensorflowlite_flex.dll`
tflite_flex_shared_library(
  name = "tensorflowlite_flex",
  models = [
      ":model_one.tflite",
      ":model_two.tflite",
  ],
)

El destino recién agregado se puede compilar de la siguiente manera:

bazel build -c opt --cxxopt='--std=c++17' \
      --config=monolithic \
      --host_crosstool_top=@bazel_tools//tools/cpp:toolchain \
      //tmp:tensorflowlite_flex

y para Android (reemplaza android_arm por android_arm64 para 64 bits):

bazel build -c opt --cxxopt='--std=c++17' \
      --config=android_arm \
      --config=monolithic \
      --host_crosstool_top=@bazel_tools//tools/cpp:toolchain \
      //tmp:tensorflowlite_flex

Compila LiteRT de forma selectiva con Docker

En esta sección, se supone que instalaste Docker en tu máquina local y descargaste el Dockerfile de LiteRT aquí.

Después de descargar el Dockerfile anterior, puedes compilar la imagen de Docker ejecutando el siguiente comando:

docker build . -t tflite-builder -f tflite-android.Dockerfile

Cómo compilar archivos AAR para el proyecto de Android

Para descargar la secuencia de comandos para compilar con Docker, ejecuta el siguiente comando:

curl -o build_aar_with_docker.sh \
  https://raw.githubusercontent.com/tensorflow/tensorflow/master/tensorflow/lite/tools/build_aar_with_docker.sh &&
chmod +x build_aar_with_docker.sh

Luego, puedes compilar el AAR de LiteRT personalizado proporcionando las rutas de acceso a los archivos de tu modelo de la siguiente manera.

sh build_aar_with_docker.sh \
  --input_models=/a/b/model_one.tflite,/c/d/model_two.tflite \
  --target_archs=x86,x86_64,arm64-v8a,armeabi-v7a \
  --checkpoint=master \
  [--cache_dir=<path to cache directory>]

La marca checkpoint es una confirmación, una rama o una etiqueta del repo de TensorFlow que deseas extraer antes de compilar las bibliotecas. De forma predeterminada, es la rama de la versión más reciente. El comando anterior generará el archivo AAR tensorflow-lite.aar para las operaciones integradas y personalizadas de LiteRT y, de manera opcional, el archivo AAR tensorflow-lite-select-tf-ops.aar para las operaciones de Select TensorFlow en tu directorio actual.

El parámetro --cache_dir especifica el directorio de caché. Si no se proporciona, la secuencia de comandos creará un directorio llamado bazel-build-cache en el directorio de trabajo actual para el almacenamiento en caché.

Cómo agregar archivos AAR al proyecto

Agrega archivos AAR importándolos directamente a tu proyecto o publicando el AAR personalizado en tu repositorio local de Maven. Ten en cuenta que también debes agregar los archivos AAR para tensorflow-lite-select-tf-ops.aar si los generas.

Compilación selectiva para iOS

Consulta la sección sobre compilación local para configurar el entorno de compilación y el espacio de trabajo de TensorFlow. Luego, sigue la guía para usar la secuencia de comandos de compilación selectiva para iOS.