Delegado de aceleración de GPU con la API C/C++

El uso de unidades de procesamiento gráfico (GPU) para ejecutar tus modelos de aprendizaje automático (AA) puede mejorar drásticamente el rendimiento y la experiencia del usuario de las aplicaciones habilitadas para el AA. En dispositivos Android, puedes habilitar la ejecución acelerada por GPU de tus modelos mediante un delegado y una de las siguientes APIs:

  • API de intérprete: guía
  • API nativa (C/C++): esta guía

En esta guía, se abordan los usos avanzados del delegado de GPU para la API C y la API de C++, y el uso de modelos cuantizados. Para obtener más información sobre el uso del delegado de GPU para TensorFlow Lite, incluidas las prácticas recomendadas y las técnicas avanzadas, consulta la página Delegados de GPU.

Cómo habilitar la aceleración de GPU

Para usar el delegado de GPU de TensorFlow Lite para Android en C o C++, crea el delegado con TfLiteGpuDelegateV2Create() y destrúyelo con TfLiteGpuDelegateV2Delete(), como se muestra en el siguiente código de ejemplo:

// Set up interpreter.
auto model = FlatBufferModel::BuildFromFile(model_path);
if (!model) return false;
ops::builtin::BuiltinOpResolver op_resolver;
std::unique_ptr<Interpreter> interpreter;
InterpreterBuilder(*model, op_resolver)(&interpreter);

// NEW: Prepare GPU delegate.
auto* delegate = TfLiteGpuDelegateV2Create(/*default options=*/nullptr);
if (interpreter->ModifyGraphWithDelegate(delegate) != kTfLiteOk) return false;

// Run inference.
WriteToInputTensor(interpreter->typed_input_tensor<float>(0));
if (interpreter->Invoke() != kTfLiteOk) return false;
ReadFromOutputTensor(interpreter->typed_output_tensor<float>(0));

// NEW: Clean up.
TfLiteGpuDelegateV2Delete(delegate);

Revisa el código del objeto TfLiteGpuDelegateOptionsV2 para compilar una instancia delegada con opciones personalizadas. Puedes inicializar las opciones predeterminadas con TfLiteGpuDelegateOptionsV2Default() y, luego, modificarlas según sea necesario.

El delegado de GPU de TensorFlow Lite para Android en C o C++ usa el sistema de compilación Bazel. Puedes compilar el delegado con el siguiente comando:

bazel build -c opt --config android_arm64 tensorflow/lite/delegates/gpu:delegate                           # for static library
bazel build -c opt --config android_arm64 tensorflow/lite/delegates/gpu:libtensorflowlite_gpu_delegate.so  # for dynamic library

Cuando se llama a Interpreter::ModifyGraphWithDelegate() o Interpreter::Invoke(), el llamador debe tener un EGLContext en el subproceso actual y se debe llamar a Interpreter::Invoke() desde el mismo EGLContext. Si un EGLContext no existe, el delegado crea uno internamente. Sin embargo, debes asegurarte de que siempre se llame a Interpreter::Invoke() desde el mismo subproceso en el que se llamó a Interpreter::ModifyGraphWithDelegate().

Con TensorFlow Lite en los Servicios de Google Play:

Si usas TensorFlow Lite en la API de C de los Servicios de Google Play, deberás usar la API de Java/Kotlin a fin de verificar si hay un delegado de GPU disponible para tu dispositivo antes de inicializar el entorno de ejecución de TensorFlow Lite.

Agrega las dependencias de Gradle delegadas de la GPU a tu aplicación:

implementation 'com.google.android.gms:play-services-tflite-gpu:16.2.0'

Luego, verifica la disponibilidad de la GPU y, luego, inicializa TfLiteNative si la verificación se realiza correctamente:

Java

Task<Void> tfLiteHandleTask =
TfLiteGpu.isGpuDelegateAvailable(this)
   .onSuccessTask(gpuAvailable -> {
      TfLiteInitializationOptions options =
        TfLiteInitializationOptions.builder()
          .setEnableGpuDelegateSupport(gpuAvailable).build();
        return TfLiteNative.initialize(this, options);
      }
    );
      

Kotlin

val tfLiteHandleTask = TfLiteGpu.isGpuDelegateAvailable(this)
    .onSuccessTask { gpuAvailable ->
        val options = TfLiteInitializationOptions.Builder()
            .setEnableGpuDelegateSupport(gpuAvailable)
            .build()
        TfLiteNative.initialize(this, options)
    }
        

También debes actualizar la configuración de CMake para incluir la marca del compilador TFLITE_USE_OPAQUE_DELEGATE:

add_compile_definitions(TFLITE_USE_OPAQUE_DELEGATE)

La biblioteca FlatBuffers se usa para configurar complementos delegados, por lo que debes agregarla a las dependencias de tu código nativo. Puedes usar la configuración oficial del proyecto CMake de la siguiente manera:

target_include_directories(tflite-jni PUBLIC
        third_party/headers # flatbuffers
     ...)

También puedes simplemente agrupar los encabezados en tu app.

Por último, para usar la inferencia de GPU en tu código C, crea el delegado de GPU con TFLiteSettings:

#include "flatbuffers/flatbuffers.h"
#include "tensorflow/lite/acceleration/configuration/configuration_generated.h"

flatbuffers::FlatBufferBuilder fbb;
tflite::TFLiteSettingsBuilder builder(fbb);
const tflite::TFLiteSettings* tflite_settings =
    flatbuffers::GetTemporaryPointer(fbb, builder.Finish());

const TfLiteOpaqueDelegatePlugin* pluginCApi = TfLiteGpuDelegatePluginCApi();
TfLiteOpaqueDelegate* gpu_delegate = pluginCApi->create(tflite_settings);

Modelos cuantificados

Las bibliotecas delegadas de GPU de Android admiten modelos cuantificados de forma predeterminada. No es necesario que realices ningún cambio en el código para usar modelos cuantizados con el delegado de GPU. En la siguiente sección, se explica cómo inhabilitar la compatibilidad cuantizada con fines experimentales o de prueba.

Inhabilita la compatibilidad con modelos cuantizados

En el siguiente código, se muestra cómo inhabilitar la compatibilidad con modelos cuantizados.

C++

TfLiteGpuDelegateOptionsV2 options = TfLiteGpuDelegateOptionsV2Default();
options.experimental_flags = TFLITE_GPU_EXPERIMENTAL_FLAGS_NONE;

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

Para obtener más información sobre cómo ejecutar modelos cuantizados con aceleración de GPU, consulta la descripción general del delegado de GPU.