Delegado de aceleração de GPU com a API C/C++

O uso de unidades de processamento gráfico (GPUs) para executar modelos de machine learning (ML) pode melhorar muito o desempenho e a experiência do usuário dos seus aplicativos ativados para ML. Em dispositivos Android, é possível ativar a execução acelerada da GPU dos modelos usando um delegado e uma das APIs abaixo:

  • API Interpreter: guia
  • API Native (C/C++): este guia

Este guia aborda usos avançados do delegado de GPU para a API C e a API C++, além do uso de modelos quantizados. Para saber mais sobre como usar o delegado de GPU no TensorFlow Lite, incluindo práticas recomendadas e técnicas avançadas, consulte a página Delegados de GPU.

Ativar aceleração de GPU

Para usar o delegado da GPU do TensorFlow Lite para Android em C ou C++, crie o delegado com TfLiteGpuDelegateV2Create() e destrua-o com TfLiteGpuDelegateV2Delete(), conforme mostrado no código de exemplo a seguir:

// 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);

Revise o código do objeto TfLiteGpuDelegateOptionsV2 para criar uma instância delegada com opções personalizadas. É possível inicializar as opções padrão com TfLiteGpuDelegateOptionsV2Default() e modificá-las conforme necessário.

O delegado de GPU do TensorFlow Lite para Android em C ou C++ usa o sistema de build Bazel. É possível criar o delegado usando o seguinte 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

Ao chamar Interpreter::ModifyGraphWithDelegate() ou Interpreter::Invoke(), o autor da chamada precisa ter um EGLContext na linha de execução atual, e Interpreter::Invoke() precisa ser chamado no mesmo EGLContext. Se um EGLContext não existir, o delegado criará um internamente, mas você precisará garantir que Interpreter::Invoke() seja sempre chamado na mesma linha de execução em que Interpreter::ModifyGraphWithDelegate() foi chamado.

Com o TensorFlow Lite no Google Play Services:

Se você estiver usando o TensorFlow Lite na API C do Google Play Services, será necessário usar a API Java/Kotlin para verificar se um delegado de GPU está disponível para seu dispositivo antes de inicializar o ambiente de execução do TensorFlow Lite.

Adicione as dependências do Gradle delegadas à GPU ao aplicativo:

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

Em seguida, verifique a disponibilidade da GPU e inicialize TfLiteNative se a verificação for bem-sucedida:

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)
    }
        

Também é necessário atualizar a configuração do CMake para incluir a flag do compilador TFLITE_USE_OPAQUE_DELEGATE:

add_compile_definitions(TFLITE_USE_OPAQUE_DELEGATE)

A biblioteca FlatBuffers é usada para configurar plug-ins delegados. Portanto, é necessário adicioná-la às dependências do seu código nativo. Você pode usar a configuração oficial do projeto CMake da seguinte maneira:

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

Você também pode simplesmente agrupar os cabeçalhos ao seu aplicativo.

Por fim, para usar a inferência de GPU no código C, crie o 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 quantizados

Por padrão, as bibliotecas delegadas de GPU do Android oferecem suporte a modelos quantizados. Não é necessário fazer nenhuma mudança no código para usar modelos quantizados com o delegado da GPU. A seção a seguir explica como desativar o suporte quantizado para fins de teste ou experimentais.

Desativar suporte a modelos quantizados

O código a seguir mostra como desativar o suporte para modelos quantizados.

C++

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

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

Para saber mais sobre como executar modelos quantizados com aceleração de GPU, consulte a visão geral do delegado de GPU.