TensorFlow Lite suporta 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 iOS.
As GPUs são projetadas para ter alto rendimento 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 realizados em paralelo, normalmente resultando em menor latência. No melhor cenário, a inferência na GPU pode agora ser executada com rapidez suficiente para aplicativos em tempo real não disponíveis anteriormente.
Ao contrário das CPUs, as GPUs computam com números de ponto flutuante de 16 ou 32 bits e não requerem quantização para desempenho ideal. O delegado aceita modelos quantizados de 8 bits, mas o cálculo será executado em números de ponto flutuante. Consulte a documentação avançada para mais detalhes.
Outro benefício com a inferência de GPU é sua eficiência de energia. As GPUs realizam os cálculos de maneira muito eficiente e otimizada, de forma 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 testar o delegado da GPU é seguir os tutoriais abaixo, que descrevem a construção de nossos aplicativos de demonstração de classificação com suporte para GPU. O código da GPU é apenas binário por enquanto; o código-fonte será aberto em breve. Depois de entender como fazer nossas demonstrações funcionarem, você pode experimentar em seus próprios modelos personalizados.
Android (com Android Studio)
Para um tutorial passo-a-passo, assistir a GPU Delegado para Android vídeo.
Etapa 1. Clone o código-fonte do TensorFlow e abra-o no Android Studio
git clone https://github.com/tensorflow/tensorflow
Passo 2. Editar app/build.gradle
usar o AAR GPU noturno
Adicione o tensorflow-lite-gpu
pacote ao lado do existente tensorflow-lite
pacote no existente dependencies
bloco.
dependencies {
...
implementation 'org.tensorflow:tensorflow-lite:2.3.0'
implementation 'org.tensorflow:tensorflow-lite-gpu:2.3.0'
}
Etapa 3. Construir e executar
Execute → Execute o 'app'. Ao executar o aplicativo, você verá um botão para habilitar a GPU. Mude de modelo quantizado para modelo flutuante e clique em GPU para executar na GPU.
iOS (com XCode)
Para um tutorial passo-a-passo, assistir a GPU Delegado para iOS vídeo.
Etapa 1. Obtenha o código-fonte demo e certifique-se de que ele compila.
Siga o nosso iOS Demo App tutorial . Isso o levará a um ponto em que a demonstração não modificada da câmera iOS está funcionando em seu telefone.
Etapa 2. Modificar 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 binário. Você pode incluí-los especificando subspec. Para TensorFlowLiteSwift
pod:
pod 'TensorFlowLiteSwift/Metal', '~> 0.0.1-nightly',
OU
pod 'TensorFlowLiteSwift', '~> 0.0.1-nightly', :subspecs => ['Metal']
Você pode fazer da mesma forma para TensorFlowLiteObjC
ou TensorFlowLitC
se você quiser usar o Objective-C (a partir de 2.4.0 release) ou C API.
Antes do lançamento 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. Habilite o delegado GPU
Para ativar o código que utilizará o delegado GPU, você vai precisar para mudar TFLITE_USE_GPU_DELEGATE
0-1 em CameraExampleViewController.h
.
#define TFLITE_USE_GPU_DELEGATE 1
Etapa 4. Construir e executar o aplicativo de demonstração
Depois de seguir a etapa anterior, você deve ser capaz de 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 alterar para uma versão de compilação com as configurações de Metal ideais adequadas. Em particular, para editar essas configurações vá para o Product > Scheme > Edit Scheme...
. Selecione Run
. Por Info
guia, mudança Build Configuration
, a partir Debug
para Release
, desmarque Debug executable
.
Em seguida, clique no Options
guia e mudança GPU Frame Capture
para Disabled
e Metal API Validation
para Disabled
.
Por último, certifique-se de selecionar compilações somente de lançamento na arquitetura de 64 bits. Sob Project navigator -> tflite_camera_example -> PROJECT -> tflite_camera_example -> Build Settings
definir Build Active Architecture Only > Release
para Sim.
Experimentando o delegado GPU em seu próprio modelo
Android
Há duas maneiras para invocar aceleração modelo, dependendo se você estiver usando o Android Estúdio ML Model Binding ou TensorFlow Lite intérprete.
Intérprete TensorFlow Lite
Veja a demonstração para ver como adicionar o delegado. Em seu aplicativo, adicione o AAR como acima, importação org.tensorflow.lite.gpu.GpuDelegate
módulo, e usar o addDelegate
função para registrar o delegado GPU para o intérprete:
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 ... }
Objective-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 não é uma falha de tempo de execução real, mas algo que o desenvolvedor pode observar enquanto tenta fazer com que a rede seja executada no delegado.
Dicas para otimização
Otimizando para dispositivos móveis
Algumas operações que são triviais na CPU podem ter um custo alto para a GPU em dispositivos móveis. Operações remodelar são particularmente caro para executar, incluindo BATCH_TO_SPACE
, SPACE_TO_BATCH
, SPACE_TO_DEPTH
, e assim por diante. Você deve examinar atentamente o uso de operações de remodelagem e considerar que podem ter sido aplicadas 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 de um tensor de forma [B,H,W,5]
vai realizar sobre o mesmo 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 para RGBX de 4 canais) pode ser evitada.
Para obter o melhor desempenho, você deve considerar 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 da GPU permite que você carregue o código do kernel pré-compilado e os dados do modelo serializados e salvos no 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 Delegado serialização .