O Google I/O é um embrulho! Fique por dentro das sessões do TensorFlow Ver sessões

Delegado da GPU TensorFlow Lite

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.

executando demonstração gpu do Android e alternar para 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 .

configurando a liberação

Em seguida, clique no Options guia e mudança GPU Frame Capture para Disabled e Metal API Validation para Disabled .

configurando opções de metal

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.

configurando opções de lançamento

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 .