O TensorFlow Lite oferece suporte a vários aceleradores de hardware. Este documento descreve como usar o back-end da GPU usando as APIs delegadas do TensorFlow Lite no Android e no iOS.
As GPUs são projetadas para ter alta taxa de transferência para cargas de trabalho massivamente paralelizáveis. Assim, eles são adequados para redes neurais profundas, que consistem em um grande número de operadores, cada um trabalhando em alguns tensores de entrada que podem ser facilmente divididos em cargas de trabalho menores e executados em paralelo, normalmente resultando em menor latência. No melhor cenário, a inferência na GPU agora pode ser executada com rapidez suficiente para aplicativos em tempo real anteriormente não disponíveis.
Ao contrário das CPUs, as GPUs computam com números de ponto flutuante de 16 bits ou 32 bits e não requerem quantização para um desempenho ideal. O delegado aceita modelos quantizados de 8 bits, mas o cálculo será realizado em números de ponto flutuante. Consulte a documentação avançada para obter detalhes.
Outro benefício com a inferência de GPU é sua eficiência de energia. As GPUs realizam os cálculos de forma muito eficiente e otimizada, de modo que consomem menos energia e geram menos calor do que quando a mesma tarefa é executada em CPUs.
Tutoriais de aplicativos de demonstração
A maneira mais fácil de experimentar o delegado de GPU é seguir os tutoriais abaixo, que passam pela construção de nossos aplicativos de demonstração de classificação com suporte a GPU. O código da GPU é apenas binário por enquanto; será de código aberto em breve. Depois de entender como fazer nossas demonstrações funcionarem, você pode experimentar isso em seus próprios modelos personalizados.
Android (com Android Studio)
Para um tutorial passo a passo, assista ao vídeo GPU Delegate para Android .
Etapa 1. Clone o código-fonte do TensorFlow e abra-o no Android Studio
git clone https://github.com/tensorflow/tensorflow
Etapa 2. Edite app/build.gradle
para usar o GPU AAR noturno
Adicione o tensorflow-lite-gpu
junto com o pacote tensorflow-lite
existente no bloco de dependencies
existente.
dependencies {
...
implementation 'org.tensorflow:tensorflow-lite:2.3.0'
implementation 'org.tensorflow:tensorflow-lite-gpu:2.3.0'
}
Etapa 3. Construir e executar
Executar → Executar 'aplicativo'. Ao executar o aplicativo, você verá um botão para habilitar a GPU. Mude de modelo quantizado para flutuante e clique em GPU para executar na GPU.
iOS (com XCode)
Para um tutorial passo a passo, assista ao vídeo GPU Delegate para iOS .
Etapa 1. Obtenha o código-fonte de demonstração e certifique-se de compilar.
Siga nosso tutorial do aplicativo de demonstração para iOS. Isso levará você a um ponto em que a demonstração da câmera iOS não modificada está funcionando no seu telefone.
Etapa 2. Modifique o Podfile para usar o TensorFlow Lite GPU CocoaPod
A partir da versão 2.3.0, por padrão, o delegado da GPU é excluído do pod para reduzir o tamanho do binário. Você pode incluí-los especificando subspec. Para o pod TensorFlowLiteSwift
:
pod 'TensorFlowLiteSwift/Metal', '~> 0.0.1-nightly',
OU
pod 'TensorFlowLiteSwift', '~> 0.0.1-nightly', :subspecs => ['Metal']
Você pode fazer o mesmo para TensorFlowLiteObjC
ou TensorFlowLitC
se quiser usar o Objective-C (da versão 2.4.0) ou a API C.
Antes da versão 2.3.0
Até TensorFlow Lite 2.0.0
Construímos um CocoaPod binário que inclui o delegado da GPU. Para mudar o projeto para usá-lo, modifique o arquivo `tensorflow/tensorflow/lite/examples/ios/camera/Podfile` para usar o pod `TensorFlowLiteGpuExperimental` em vez de `TensorFlowLite`.
target 'YourProjectName'
# pod 'TensorFlowLite', '1.12.0'
pod 'TensorFlowLiteGpuExperimental'
Até TensorFlow Lite 2.2.0
Do TensorFlow Lite 2.1.0 ao 2.2.0, o delegado da GPU está incluído no pod `TensorFlowLiteC`. Você pode escolher entre `TensorFlowLiteC` e `TensorFlowLiteSwift` dependendo do idioma.
Etapa 3. Ative o delegado da GPU
Para habilitar o código que usará o delegado da GPU, você precisará alterar TFLITE_USE_GPU_DELEGATE
de 0 para 1 em CameraExampleViewController.h
.
#define TFLITE_USE_GPU_DELEGATE 1
Etapa 4. Crie e execute o aplicativo de demonstração
Depois de seguir a etapa anterior, você poderá executar o aplicativo.
Etapa 5. Modo de liberação
Enquanto na Etapa 4 você executou no modo de depuração, para obter melhor desempenho, você deve mudar para uma versão de versão com as configurações ideais do Metal apropriadas. Em particular, para editar essas configurações, vá para Product > Scheme > Edit Scheme...
. Selecione Run
. Na guia Info
, altere Build Configuration
, de Debug
para Release
, desmarque Debug executable
.
Em seguida, clique na guia Options
e altere GPU Frame Capture
para Disabled
e Metal API Validation
para Disabled
.
Por último, certifique-se de selecionar compilações somente de versão na arquitetura de 64 bits. Em Project navigator -> tflite_camera_example -> PROJECT -> tflite_camera_example -> Build Settings
defina Build Active Architecture Only > Release
para Yes.
Tentando o delegado da GPU em seu próprio modelo
Android
Há duas maneiras de invocar a aceleração de modelo, dependendo de você estar usando o Android Studio ML Model Binding ou o TensorFlow Lite Interpreter.
Interpretador do TensorFlow Lite
Veja a demonstração para ver como adicionar o delegado. Em seu aplicativo, adicione o AAR como acima, importe o módulo org.tensorflow.lite.gpu.GpuDelegate
e use a função addDelegate
para registrar o delegado da GPU no interpretador:
Kotlin
import org.tensorflow.lite.Interpreter import org.tensorflow.lite.gpu.CompatibilityList import org.tensorflow.lite.gpu.GpuDelegate val compatList = CompatibilityList() val options = Interpreter.Options().apply{ if(compatList.isDelegateSupportedOnThisDevice){ // if the device has a supported GPU, add the GPU delegate val delegateOptions = compatList.bestOptionsForThisDevice this.addDelegate(GpuDelegate(delegateOptions)) } else { // if the GPU is not supported, run on 4 threads this.setNumThreads(4) } } val interpreter = Interpreter(model, options) // Run inference writeToInput(input) interpreter.run(input, output) readFromOutput(output)
Java
import org.tensorflow.lite.Interpreter; import org.tensorflow.lite.gpu.CompatibilityList; import org.tensorflow.lite.gpu.GpuDelegate; // Initialize interpreter with GPU delegate Interpreter.Options options = new Interpreter.Options(); CompatibilityList compatList = CompatibilityList(); if(compatList.isDelegateSupportedOnThisDevice()){ // if the device has a supported GPU, add the GPU delegate GpuDelegate.Options delegateOptions = compatList.getBestOptionsForThisDevice(); GpuDelegate gpuDelegate = new GpuDelegate(delegateOptions); options.addDelegate(gpuDelegate); } else { // if the GPU is not supported, run on 4 threads options.setNumThreads(4); } Interpreter interpreter = new Interpreter(model, options); // Run inference writeToInput(input); interpreter.run(input, output); readFromOutput(output);
iOS
Rápido
import TensorFlowLite // Load model ... // Initialize TensorFlow Lite interpreter with the GPU delegate. let delegate = MetalDelegate() if let interpreter = try Interpreter(modelPath: modelPath, delegates: [delegate]) { // Run inference ... }
Objetivo-C
// Import module when using CocoaPods with module support @import TFLTensorFlowLite; // Or import following headers manually #import "tensorflow/lite/objc/apis/TFLMetalDelegate.h" #import "tensorflow/lite/objc/apis/TFLTensorFlowLite.h" // Initialize GPU delegate TFLMetalDelegate* metalDelegate = [[TFLMetalDelegate alloc] init]; // Initialize interpreter with model path and GPU delegate TFLInterpreterOptions* options = [[TFLInterpreterOptions alloc] init]; NSError* error = nil; TFLInterpreter* interpreter = [[TFLInterpreter alloc] initWithModelPath:modelPath options:options delegates:@[ metalDelegate ] error:&error]; if (error != nil) { /* Error handling... */ } if (![interpreter allocateTensorsWithError:&error]) { /* Error handling... */ } if (error != nil) { /* Error handling... */ } // Run inference ... ```
C (Até 2.3.0)
#include "tensorflow/lite/c/c_api.h" #include "tensorflow/lite/delegates/gpu/metal_delegate.h" // Initialize model TfLiteModel* model = TfLiteModelCreateFromFile(model_path); // Initialize interpreter with GPU delegate TfLiteInterpreterOptions* options = TfLiteInterpreterOptionsCreate(); TfLiteDelegate* delegate = TFLGPUDelegateCreate(nil); // default config TfLiteInterpreterOptionsAddDelegate(options, metal_delegate); TfLiteInterpreter* interpreter = TfLiteInterpreterCreate(model, options); TfLiteInterpreterOptionsDelete(options); TfLiteInterpreterAllocateTensors(interpreter); NSMutableData *input_data = [NSMutableData dataWithLength:input_size * sizeof(float)]; NSMutableData *output_data = [NSMutableData dataWithLength:output_size * sizeof(float)]; TfLiteTensor* input = TfLiteInterpreterGetInputTensor(interpreter, 0); const TfLiteTensor* output = TfLiteInterpreterGetOutputTensor(interpreter, 0); // Run inference TfLiteTensorCopyFromBuffer(input, inputData.bytes, inputData.length); TfLiteInterpreterInvoke(interpreter); TfLiteTensorCopyToBuffer(output, outputData.mutableBytes, outputData.length); // Clean up TfLiteInterpreterDelete(interpreter); TFLGpuDelegateDelete(metal_delegate); TfLiteModelDelete(model);
## Supported Models and Ops
With the release of the GPU delegate, we included a handful of models that can
be run on the backend:
* [MobileNet v1 (224x224) image classification](https://ai.googleblog.com/2017/06/mobilenets-open-source-models-for.html) [[download]](https://storage.googleapis.com/download.tensorflow.org/models/tflite/gpu/mobilenet_v1_1.0_224.tflite)
<br /><i>(image classification model designed for mobile and embedded based vision applications)</i>
* [DeepLab segmentation (257x257)](https://ai.googleblog.com/2018/03/semantic-image-segmentation-with.html) [[download]](https://storage.googleapis.com/download.tensorflow.org/models/tflite/gpu/deeplabv3_257_mv_gpu.tflite)
<br /><i>(image segmentation model that assigns semantic labels (e.g., dog, cat, car) to every pixel in the input image)</i>
* [MobileNet SSD object detection](https://ai.googleblog.com/2018/07/accelerated-training-and-inference-with.html) [[download]](https://storage.googleapis.com/download.tensorflow.org/models/tflite/gpu/mobile_ssd_v2_float_coco.tflite)
<br /><i>(image classification model that detects multiple objects with bounding boxes)</i>
* [PoseNet for pose estimation](https://github.com/tensorflow/tfjs-models/tree/master/posenet) [[download]](https://storage.googleapis.com/download.tensorflow.org/models/tflite/gpu/multi_person_mobilenet_v1_075_float.tflite)
<br /><i>(vision model that estimates the poses of a person(s) in image or video)</i>
To see a full list of supported ops, please see the
[advanced documentation](gpu_advanced).
## Non-supported models and ops
If some of the ops are not supported by the GPU delegate, the framework will
only run a part of the graph on the GPU and the remaining part on the CPU. Due
to the high cost of CPU/GPU synchronization, a split execution mode like this
will often result in slower performance than when the whole network is run on
the CPU alone. In this case, the user will get a warning like:
```none
WARNING: op code #42 cannot be handled by this delegate.
```
Não fornecemos um retorno de chamada para essa falha, pois essa não é uma falha real em tempo de execução, mas algo que o desenvolvedor pode observar enquanto tenta fazer com que a rede seja executada no delegado.
Dicas para otimização
Otimização para dispositivos móveis
Algumas operações que são triviais na CPU podem ter um alto custo para a GPU em dispositivos móveis. As operações de remodelação são particularmente caras para executar, incluindo BATCH_TO_SPACE
, SPACE_TO_BATCH
, SPACE_TO_DEPTH
e assim por diante. Você deve examinar de perto o uso de operações de remodelação e considerar que pode ter sido aplicado apenas para explorar dados ou para iterações iniciais de seu modelo. Removê-los pode melhorar significativamente o desempenho.
Na GPU, os dados do tensor são divididos em 4 canais. Assim, um cálculo em um tensor de forma [B,H,W,5]
terá o mesmo desempenho em um tensor de forma [B,H,W,8]
mas significativamente pior do que [B,H,W,4]
. Nesse sentido, se o hardware da câmera suportar quadros de imagem em RGBA, alimentar essa entrada de 4 canais é significativamente mais rápido, pois uma cópia de memória (de RGB de 3 canais a RGBX de 4 canais) pode ser evitada.
Para obter o melhor desempenho, considere treinar novamente o classificador com uma arquitetura de rede otimizada para dispositivos móveis. A otimização para inferência no dispositivo pode reduzir drasticamente a latência e o consumo de energia aproveitando os recursos de hardware móvel.
Reduzindo o tempo de inicialização com serialização
O recurso de delegado de GPU permite que você carregue a partir de código de kernel pré-compilado e dados de modelo serializados e salvos em disco de execuções anteriores. Essa abordagem evita a recompilação e reduz o tempo de inicialização em até 90%. Para obter instruções sobre como aplicar a serialização ao seu projeto, consulte GPU Delegate Serialization .