Delegados de GPU para o TensorFlow Lite

O uso de unidades de processamento gráfico (GPUs) para executar modelos de machine learning (ML) pode melhorar drasticamente o desempenho do modelo e a experiência do usuário dos aplicativos com ML ativado. O TensorFlow Lite permite o uso de GPUs e outros processadores especializados com o driver de hardware chamado delegados. A ativação do uso de GPUs com os aplicativos de ML do TensorFlow Lite pode oferecer os seguintes benefícios:

  • Velocidade: as GPUs são criadas para alta capacidade de cargas de trabalho em paralelo. Esse design os torna adequados para redes neurais profundas, que consistem em um grande número de operadores, cada um trabalhando com tensores de entrada que podem ser processados em paralelo, o que normalmente resulta em menor latência. No melhor cenário, a execução do modelo em uma GPU pode ser rápida o suficiente para ativar aplicativos em tempo real que não eram possíveis antes.
  • Eficiência de energia: as GPUs realizam cálculos de ML de maneira muito eficiente e otimizada, normalmente consumindo menos energia e gerando menos calor do que a mesma tarefa executada em CPUs.

Neste documento, você terá uma visão geral da compatibilidade com GPUs no TensorFlow Lite e alguns usos avançados para processadores de GPU. Para informações mais específicas sobre a implementação do suporte a GPUs em plataformas específicas, consulte estes guias:

Suporte a operações de ML da GPU

Há algumas limitações em quais operações de ML, ou ops, podem ser aceleradas pelo delegado da GPU do TensorFlow Lite. O delegado é compatível com as seguintes operações com precisão de ponto flutuante de 16 e 32 bits:

  • ADD
  • AVERAGE_POOL_2D
  • CONCATENATION
  • CONV_2D
  • DEPTHWISE_CONV_2D v1-2
  • EXP
  • FULLY_CONNECTED
  • LOGICAL_AND
  • LOGISTIC
  • LSTM v2 (Basic LSTM only)
  • MAX_POOL_2D
  • MAXIMUM
  • MINIMUM
  • MUL
  • PAD
  • PRELU
  • RELU
  • RELU6
  • RESHAPE
  • RESIZE_BILINEAR v1-3
  • SOFTMAX
  • STRIDED_SLICE
  • SUB
  • TRANSPOSE_CONV

Por padrão, todas as operações são suportadas apenas na versão 1. Ativar o suporte à quantização ativa as versões apropriadas, por exemplo, ADD v2.

Solução de problemas de suporte a GPUs

Se algumas das operações não tiverem suporte do delegado da GPU, o framework executará apenas uma parte do gráfico na GPU e a parte restante na CPU. Devido ao alto custo da sincronização entre CPU/GPU, um modo de execução dividida como esse geralmente resulta em um desempenho mais lento do que quando toda a rede é executada na CPU sozinha. Nesse caso, o aplicativo gera um aviso, como:

WARNING: op code #42 cannot be handled by this delegate.

Não há callback para falhas desse tipo, já que não é uma falha real no ambiente de execução. Ao testar a execução do seu modelo com o delegado da GPU, esteja alerta para esses avisos. Um número alto desses avisos pode indicar que o modelo não é adequado para uso para aceleração de GPU e pode exigir a refatoração do modelo.

Exemplos de modelos

Os modelos de exemplo abaixo foram criados para aproveitar a aceleração de GPU com o TensorFlow Lite e são fornecidos para referência e teste:

Como otimizar para GPUs

As técnicas a seguir podem ajudar você a conseguir melhor desempenho ao executar modelos em hardware de GPU usando o delegado de GPU do TensorFlow Lite:

  • Operações de remodelação: algumas operações rápidas em uma CPU podem ter um alto custo para a GPU em dispositivos móveis. As operações de remodelação são particularmente caras de executar, incluindo BATCH_TO_SPACE, SPACE_TO_BATCH, SPACE_TO_DEPTH e assim por diante. Examine com cuidado o uso de operações de remodelação e considere que elas podem ter sido aplicadas apenas para explorar dados ou para as iterações iniciais do seu modelo. A remoção deles pode melhorar significativamente o desempenho.

  • Canais de dados de imagem: na GPU, os dados do tensor são divididos em quatro canais. Portanto, o cálculo de um tensor com a forma [B,H,W,5] tem o mesmo desempenho em um tensor de forma [B,H,W,8], mas significativamente pior do que [B,H,W,4]. Se o hardware da câmera que você está usando oferecer suporte a frames de imagem em RGBA, a alimentação dessa entrada de quatro canais será significativamente mais rápida, porque isso evita uma cópia de memória do RGB de três canais para o RGBX de quatro canais.

  • Modelos otimizados para dispositivos móveis: para ter o melhor desempenho, considere treinar novamente seu classificador com uma arquitetura de rede otimizada para dispositivos móveis. A otimização para inferências no dispositivo pode reduzir drasticamente a latência e o consumo de energia ao aproveitar os recursos de hardware do dispositivo móvel.

Suporte avançado a GPUs

É possível usar outras técnicas avançadas com o processamento de GPU para permitir um desempenho ainda melhor dos modelos, incluindo quantização e serialização. As seções a seguir descrevem essas técnicas em mais detalhes.

Como usar modelos quantizados

Esta seção explica como o delegado da GPU acelera modelos quantizados de 8 bits, incluindo:

Para otimizar o desempenho, use modelos que tenham tensores de entrada e saída de ponto flutuante.

Como isso funciona?

Como o back-end da GPU só oferece suporte à execução de ponto flutuante, executamos modelos quantizados fornecendo uma "visualização de ponto flutuante" do modelo original. De modo geral, isso envolve as seguintes etapas:

  • Os tensores constantes (como pesos/vieses) são desquantizados uma vez na memória da GPU. Essa operação acontece quando o delegado é ativado para o TensorFlow Lite.

  • As entradas e saídas do programa de GPU, se quantizadas de 8 bits, são desquantizadas e quantizadas (respectivamente) para cada inferência. Essa operação é feita na CPU usando os kernels otimizados do TensorFlow Lite.

  • Simuladores de quantização são inseridos entre operações para imitar o comportamento quantizado. Essa abordagem é necessária para modelos em que as operações esperam que as ativações sigam os limites aprendidos durante a quantização.

Para informações sobre como ativar esse recurso com o delegado da GPU, consulte estas informações:

Como reduzir o tempo de inicialização com serialização

O recurso delegado da GPU permite carregar 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 pode reduzir o tempo de inicialização em até 90%. Essa melhoria é alcançada pela troca de espaço em disco para economizar tempo. É possível ativar esse recurso com algumas opções de configuração, conforme mostrado nos exemplos de código a seguir:

C++

    TfLiteGpuDelegateOptionsV2 options = TfLiteGpuDelegateOptionsV2Default();
    options.experimental_flags |= TFLITE_GPU_EXPERIMENTAL_FLAGS_ENABLE_SERIALIZATION;
    options.serialization_dir = kTmpDir;
    options.model_token = kModelToken;

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

Java

    GpuDelegate delegate = new GpuDelegate(
      new GpuDelegate.Options().setSerializationParams(
        /* serializationDir= */ serializationDir,
        /* modelToken= */ modelToken));

    Interpreter.Options options = (new Interpreter.Options()).addDelegate(delegate);
      

Ao usar o recurso de serialização, verifique se o código está em conformidade com estas regras de implementação:

  • Armazene os dados de serialização em um diretório que não possa ser acessado por outros apps. Em dispositivos Android, use getCodeCacheDir(), que aponta para um local particular do aplicativo atual.
  • O token do modelo precisa ser exclusivo do dispositivo do modelo específico. É possível calcular um token de modelo gerando uma impressão digital a partir dos dados do modelo usando bibliotecas como farmhash::Fingerprint64.