Delegati GPU per TensorFlow Lite

L'utilizzo di unità di elaborazione grafica (GPU) per eseguire i modelli di machine learning (ML) può migliorare notevolmente le prestazioni del modello e l'esperienza utente delle applicazioni abilitate per ML. TensorFlow Lite consente l'uso di GPU e altri processori specializzati tramite driver hardware chiamati delegati . Abilitare l'uso delle GPU con le tue applicazioni TensorFlow Lite ML può offrire i seguenti vantaggi:

  • Velocità : le GPU sono progettate per un throughput elevato di carichi di lavoro estremamente paralleli. Questo design li rende particolarmente adatti per le reti neurali profonde, costituite da un numero enorme di operatori, ciascuno dei quali lavora su tensori di input che possono essere elaborati in parallelo, il che in genere si traduce in una latenza inferiore. Nello scenario migliore, l'esecuzione del modello su una GPU potrebbe essere sufficientemente veloce da abilitare applicazioni in tempo reale che in precedenza non erano possibili.
  • Efficienza energetica : le GPU eseguono calcoli ML in modo molto efficiente e ottimizzato, in genere consumando meno energia e generando meno calore rispetto alla stessa attività eseguita sulle CPU.

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

Supporto per operazioni GPU ML

Esistono alcune limitazioni alle operazioni, o ops , 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 bit 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'abilitazione del supporto della quantizzazione abilita le versioni appropriate, ad esempio ADD v2.

Risoluzione dei problemi relativi al supporto 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 del costo elevato della sincronizzazione CPU/GPU, una modalità di esecuzione divisa come questa spesso comporta prestazioni più lente rispetto a quando l'intera rete viene eseguita solo sulla CPU. In questo caso, l'applicazione genera avvisi, come ad esempio:

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

Non è prevista alcuna richiamata per errori di questo tipo, poiché non si tratta di un errore effettivo in fase di esecuzione. Quando testi l'esecuzione del tuo modello con il delegato GPU, dovresti prestare attenzione a 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 realizzati per sfruttare l'accelerazione GPU con TensorFlow Lite e vengono forniti come riferimento e test:

Ottimizzazione per GPU

Le seguenti tecniche possono aiutarti a ottenere prestazioni migliori quando esegui modelli su hardware GPU utilizzando il delegato GPU TensorFlow Lite:

  • Operazioni di rimodellamento : alcune operazioni veloci su una CPU potrebbero avere un costo elevato per la GPU sui dispositivi mobili. Le operazioni di rimodellamento sono particolarmente costose da eseguire, incluse BATCH_TO_SPACE , SPACE_TO_BATCH , SPACE_TO_DEPTH e così via. Dovresti esaminare attentamente l'uso delle operazioni di ridefinizione e considerare che potrebbero essere state applicate solo per l'esplorazione dei dati o per le prime iterazioni del modello. Rimuoverli può migliorare significativamente le prestazioni.

  • Canali dati immagine : sulla GPU, i dati del tensore vengono suddivisi in 4 canali, quindi un calcolo su un tensore con la forma [B,H,W,5] esegue più o meno lo stesso su un tensore di forma [B,H,W,8] , ma significativamente peggiore di [B,H,W,4] . Se l'hardware della fotocamera in uso supporta i fotogrammi di immagine in RGBA, l'alimentazione dell'input a 4 canali è significativamente più veloce, poiché evita una copia della memoria da RGB a 3 canali a RGBX a 4 canali.

  • Modelli ottimizzati per dispositivi mobili : per ottenere prestazioni ottimali, dovresti prendere in considerazione la possibilità di riqualificare il tuo classificatore con un'architettura di rete ottimizzata per dispositivi mobili. L'ottimizzazione dell'inferenza sul dispositivo può ridurre drasticamente la latenza e il consumo energetico sfruttando le funzionalità dell'hardware mobile.

Supporto GPU avanzato

Puoi utilizzare tecniche aggiuntive e avanzate con l'elaborazione GPU per ottenere prestazioni ancora migliori per i tuoi modelli, incluse la quantizzazione e la serializzazione. Le sezioni seguenti descrivono queste tecniche in maggiore dettaglio.

Utilizzo di modelli quantizzati

Questa sezione spiega come il delegato GPU accelera i modelli quantizzati a 8 bit, inclusi i seguenti:

Per ottimizzare le prestazioni, utilizzare modelli che dispongono sia di tensori di input che 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. Ad alto livello, ciò comporta i seguenti passaggi:

  • I tensori costanti (come pesi/bias) vengono dequantizzati una volta entrati nella memoria della GPU. Questa operazione avviene quando il delegato è abilitato per TensorFlow Lite.

  • Gli input e gli output del programma GPU, se quantizzati a 8 bit, vengono dequantizzati e quantizzati (rispettivamente) per ciascuna 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 gli operatori si aspettano che le attivazioni seguano i limiti appresi durante la quantizzazione.

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

Riduzione del tempo di inizializzazione con la serializzazione

La funzionalità delegato GPU consente di caricare dal codice kernel precompilato e dai 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 scambiando spazio su disco per risparmiare tempo. Puoi abilitare questa funzione 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;
      

Giava

    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 tuo codice sia conforme a queste regole di implementazione:

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