Delegati GPU per TensorFlow Lite

L'utilizzo delle GPU (Graphics Processing Unit) per l'esecuzione dei tuoi modelli di machine learning (ML) può migliorare notevolmente le prestazioni del tuo modello e l'esperienza utente delle applicazioni abilitate per ML. TensorFlow Lite consente l'utilizzo di GPU e altri processori specializzati tramite driver hardware chiamati delegati. L'abilitazione dell'uso delle GPU con le applicazioni TensorFlow Lite ML può offrire i seguenti vantaggi:

  • Velocità - Le GPU sono progettate per un'elevata velocità effettiva di carichi di lavoro molto paralleli. Questo design le rende particolarmente adatte alle reti neurali profonde, costituite da un enorme numero di operatori, ognuno dei quali lavora su tensori di input che possono essere elaborati in parallelo, il che comporta in genere una latenza inferiore. Nello scenario migliore, l'esecuzione del modello su una GPU può essere eseguita abbastanza velocemente da abilitare applicazioni in tempo reale che in precedenza non erano possibili.
  • Efficienza energetica: le GPU eseguono i calcoli di ML in modo molto efficiente e ottimizzato, in genere consumano meno energia e generano meno calore rispetto alla stessa attività in esecuzione sulle CPU.

Questo documento fornisce una panoramica del supporto delle GPU in TensorFlow Lite e alcuni utilizzi avanzati dei processori GPU. Per informazioni più specifiche sull'implementazione del supporto delle GPU su piattaforme specifiche, consulta le seguenti guide:

Supporto per le operazioni di ML della GPU

Esistono alcune limitazioni alle operazioni, o operazioni di TensorFlow ML, che possono essere accelerate dal delegato GPU TensorFlow Lite. Il delegato supporta le seguenti operazioni con precisione in virgola mobile a 16 e 32 bit:

  • 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

Per impostazione predefinita, tutte le operazioni sono supportate solo nella versione 1. L'attivazione del supporto per la quantizzazione abilita le versioni appropriate, ad esempio ADD v2.

Risoluzione dei problemi di supporto delle GPU

Se alcune operazioni non sono supportate dal delegato GPU, il framework eseguirà solo una parte del grafico sulla GPU e la parte rimanente sulla CPU. A causa dei costi elevati della sincronizzazione di CPU/GPU, una modalità di esecuzione divisa come questa porta spesso a prestazioni inferiori rispetto a quando l'intera rete viene eseguita sulla sola CPU. In questo caso, l'applicazione genera un avviso, ad esempio:

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

Non esiste un callback per gli errori di questo tipo, poiché non si tratta di un errore di runtime effettivo. Quando testi l'esecuzione del modello con il delegato GPU, dovresti ricevere avvisi per questi avvisi. Un numero elevato di questi avvisi può indicare che il modello non è adatto all'uso per l'accelerazione GPU e potrebbe richiedere il refactoring del modello.

Modelli di esempio

I seguenti modelli di esempio sono creati per sfruttare l'accelerazione GPU con TensorFlow Lite e sono forniti per riferimento e test:

Ottimizzazione per le GPU

Le seguenti tecniche possono aiutarti a ottenere prestazioni migliori durante l'esecuzione di modelli su hardware GPU utilizzando il delegato GPU TensorFlow Lite:

  • Operazioni di rimodellamento - Alcune operazioni rapide su una CPU potrebbero avere costi elevati per la GPU sui dispositivi mobili. Le operazioni di rimodellamento sono particolarmente costose da eseguire, ad esempio BATCH_TO_SPACE, SPACE_TO_BATCH, SPACE_TO_DEPTH e così via. Dovresti esaminare attentamente l'uso delle operazioni di rimodellamento e considerare che potrebbero essere state applicate solo per l'esplorazione dei dati o per le prime iterazioni del modello. La loro rimozione può migliorare significativamente il rendimento.

  • Canali di dati immagine: sulla GPU, i dati dei tensori vengono suddivisi in quattro canali, quindi il calcolo su un tensore di forma [B,H,W,5] ha lo stesso rendimento su un tensore di forma [B,H,W,8], ma molto peggiore di [B,H,W,4]. Se l'hardware della videocamera in uso supporta i fotogrammi in RGBA, l'invio dell'input a 4 canali è notevolmente più rapido, in quanto evita una copia in memoria da RGB a 3 canali e RGBX a 4 canali.

  • Modelli ottimizzati per dispositivi mobili: per prestazioni ottimali, ti consigliamo di riaddestrare il classificatore con un'architettura di rete ottimizzata per dispositivi mobili. L'ottimizzazione per l'inferenza on-device può ridurre drasticamente la latenza e il consumo energetico grazie alle funzionalità dell'hardware mobile.

Supporto GPU avanzato

Puoi utilizzare tecniche avanzate aggiuntive con l'elaborazione GPU per migliorare ulteriormente le prestazioni dei tuoi modelli, tra cui la quantizzazione e la serializzazione. Nelle sezioni seguenti vengono descritte queste tecniche in modo più dettagliato.

Utilizzo di modelli quantizzati

Questa sezione spiega in che modo il delegato GPU accelera i modelli quantizzati a 8 bit, tra cui:

Per ottimizzare le prestazioni, utilizza modelli dotati di tensori di input e di output a virgola mobile.

Come funziona?

Poiché il backend della GPU supporta solo l'esecuzione in virgola mobile, eseguiamo modelli quantizzati fornendo una "vista in virgola mobile" del modello originale. A livello generale, sono previsti i seguenti passaggi:

  • I tensori costanti (ad esempio pesi/biasi) vengono dequantizzati una volta nella memoria della GPU. Questa operazione si verifica quando il delegato è abilitato per TensorFlow Lite.

  • Gli ingressi e gli output del programma GPU, se quantizzati a 8 bit, vengono dequantizzati e quantizzati (rispettivamente) per ogni inferenza. Questa operazione viene eseguita sulla CPU utilizzando i kernel ottimizzati di TensorFlow Lite.

  • I simulatori di quantizzazione vengono inseriti tra le operazioni per imitare il comportamento quantizzato. Questo approccio è necessario per i modelli in cui le operazioni si aspettano che le attivazioni seguano i limiti appresi durante la quantizzazione.

Per informazioni sull'abilitazione di questa funzionalità con il delegato GPU, consulta quanto segue:

Riduzione del tempo di inizializzazione con la serializzazione

La funzionalità di delega GPU consente di caricare da codice kernel precompilati e dati del modello serializzati e salvati su disco dalle esecuzioni precedenti. Questo approccio evita la ricompilazione e può ridurre i tempi di avvio fino al 90%. Questo miglioramento si ottiene mediante il risparmio di tempo dello spazio su disco. Puoi abilitare questa funzionalità con alcune opzioni di configurazione, come mostrato nei seguenti esempi di codice:

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

Quando utilizzi la funzionalità di serializzazione, assicurati che il codice sia conforme a queste regole di implementazione:

  • Archivia i dati di serializzazione in una directory non accessibile ad altre app. Sui dispositivi Android, l'icona getCodeCacheDir() che rimanda a una posizione privata per l'applicazione corrente.
  • Il token del modello deve essere univoco del dispositivo per il modello specifico. Puoi calcolare un token del modello generando un'impronta dai dati del modello utilizzando librerie come farmhash::Fingerprint64.