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

Usar unidades de procesamiento gráfico (GPU) para ejecutar tus modelos de aprendizaje automático (AA) pueden mejorar drásticamente el rendimiento y la experiencia del usuario de sus aplicaciones compatibles con el AA. En dispositivos Android, puedes habilitar la la ejecución de tus modelos con un delegado y un de las siguientes APIs:

  • API de Interpreter: 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, la API C++ y el uso de modelos cuantizados. Para obtener más información sobre el uso del delegado de GPU para LiteRT, incluidas las prácticas recomendadas y las técnicas avanzadas, consulta la GPU página de delegados.

Cómo habilitar la aceleración de GPU

Usa el delegado de GPU de LiteRT para Android en C o C++ creando la delegar con TfLiteGpuDelegateV2Create() y destruirlo 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 de objeto TfLiteGpuDelegateOptionsV2 para compilar una instancia delegada con opciones personalizadas. Puedes inicializar las opciones predeterminadas con TfLiteGpuDelegateOptionsV2Default() y, luego, modifícalos según sea necesario.

El delegado de GPU de LiteRT para Android en C o C++ usa el Sistema de compilación de Bazel. Puedes crear 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 llames a Interpreter::ModifyGraphWithDelegate() o Interpreter::Invoke(), el llamador debe tener un EGLContext en el y se debe llamar a Interpreter::Invoke() desde el mismo EGLContext. Si EGLContext no existe, el delegado crea uno a nivel interno, pero, luego, debes asegurarte de que siempre se llame a Interpreter::Invoke() desde la misma subproceso en el que se llamó a Interpreter::ModifyGraphWithDelegate().

Con LiteRT en los Servicios de Google Play, puedes hacer lo siguiente:

Si usas LiteRT en la API de C de los Servicios de Google Play, haz lo siguiente: deberás usar la API de Java/Kotlin para verificar si hay un delegado de GPU disponible. para tu dispositivo antes de inicializar el tiempo de ejecución de LiteRT.

Agrega las dependencias de Gradle del delegado de GPU a tu aplicación:

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

Comprueba la disponibilidad de la GPU e inicializa TfLiteNative si la verificación es exitosa:

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 el 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 agregarlo a las dependencias de tu código nativo. Puedes usar la configuración del proyecto oficial de CMake de la siguiente manera:

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

También puedes simplemente agrupar los encabezados para tu aplicación.

Por último, para usar la inferencia de GPU en tu código C, crea el delegado de GPU usando 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 la GPU de Android admiten modelos cuantizados de forma predeterminada. No debes tendremos que realizar cambios en el código para usar modelos cuantizados con el delegado de la GPU. El En la siguiente sección, se explica cómo inhabilitar la asistencia cuantizada para pruebas o con fines experimentales.

Inhabilitar 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 Descripción general del delegado de GPU.