Delegati LiteRT

I delegati consentono l'accelerazione hardware dei modelli LiteRT sfruttando acceleratori sul dispositivo come la GPU e il processore di segnali digitali (DSP).

Per impostazione predefinita, LiteRT utilizza kernel della CPU ottimizzati per il set di istruzioni ARM Neon. Tuttavia, la CPU è un processore multiuso che non è necessariamente ottimizzato per l'aritmetica complessa tipica dei modelli di machine learning (ad esempio, la matematica matriciale coinvolta nelle convoluzioni e nei livelli densi).

D'altra parte, la maggior parte dei cellulari moderni contiene chip più adatti a gestire queste operazioni pesanti. Il loro utilizzo per le operazioni di rete neurale offre enormi vantaggi in termini di latenza ed efficienza energetica. Ad esempio, le GPU possono fornire un aumento di velocità di 5 volte nella latenza.

Ciascuno di questi acceleratori ha API associate che consentono calcoli personalizzati, come OpenCL o OpenGL ES per la GPU mobile. In genere, devi scrivere molto codice personalizzato per eseguire una rete neurale tramite queste interfacce. Le cose si complicano ulteriormente se si considera che ogni acceleratore ha i suoi pro e contro e non può eseguire ogni operazione in una rete neurale. L'API Delegate di TensorFlow Lite risolve questo problema fungendo da ponte tra il runtime TFLite e queste API di livello inferiore.

runtime con delegati

Scegliere un delegato

LiteRT supporta più delegati, ognuno dei quali è ottimizzato per determinate piattaforme e particolari tipi di modelli. In genere, a seconda di due criteri principali, esistono più delegati applicabili al tuo caso d'uso: la piattaforma (Android o iOS?) di destinazione e il tipo di modello (in virgola mobile o quantizzato?) che stai cercando di accelerare.

Delegati per piattaforma

Multipiattaforma (Android e iOS)

  • Delegato GPU: il delegato GPU può essere utilizzato sia su Android che su iOS. È ottimizzato per l'esecuzione di modelli basati su float a 32 bit e 16 bit in cui è disponibile una GPU. Supporta anche modelli quantizzati a 8 bit e offre prestazioni della GPU pari a quelle delle versioni in virgola mobile. Per informazioni dettagliate sul delegato GPU, consulta LiteRT su GPU.

iOS

  • Delegato Core ML per iPhone e iPad più recenti: per iPhone e iPad più recenti in cui è disponibile Neural Engine, puoi utilizzare il delegato Core ML per accelerare l'inferenza per modelli in virgola mobile a 32 bit o 16 bit. Neural Engine è disponibile sui dispositivi mobili Apple con SoC A12 o versioni successive. Per una panoramica del delegato Core ML e istruzioni passo passo, vedi Delegato Core ML di LiteRT.

Delegati per tipo di modello

Ogni acceleratore è progettato tenendo conto di una determinata larghezza in bit dei dati. Se fornisci un modello in virgola mobile a un delegato che supporta solo operazioni quantizzate a 8 bit, rifiuterà tutte le operazioni e il modello verrà eseguito interamente sulla CPU. Per evitare sorprese, la tabella seguente fornisce una panoramica del supporto dei delegati in base al tipo di modello:

Tipo di modello GPU CoreML
Virgola mobile (32 bit)
Quantizzazione post-training float16
Quantizzazione dinamica dell'intervallo post-addestramento No
Quantizzazione degli interi post-addestramento No
Addestramento consapevole della quantizzazione No

Convalida del rendimento

Le informazioni in questa sezione fungono da linee guida approssimative per la preselezione dei delegati che potrebbero migliorare la tua applicazione. Tuttavia, è importante notare che ogni delegato ha un insieme predefinito di operazioni che supporta e può comportarsi in modo diverso a seconda del modello e del dispositivo. Pertanto, in genere è consigliabile eseguire alcuni benchmark per valutare l'utilità di un delegato per le tue esigenze. Ciò contribuisce anche a giustificare l'aumento delle dimensioni del file binario associato all'allegato di un delegato al runtime LiteRT.

LiteRT dispone di numerosi strumenti di valutazione delle prestazioni e dell'accuratezza che possono consentire agli sviluppatori di utilizzare i delegati nelle loro applicazioni con sicurezza. Questi strumenti sono trattati nella sezione successiva.

Strumenti per la valutazione

Latenza e footprint della memoria

Lo strumento di benchmarking di LiteRT può essere utilizzato con parametri adatti per stimare le prestazioni del modello, inclusi latenza di inferenza media, overhead di inizializzazione, footprint di memoria e così via. Questo strumento supporta più flag per determinare la migliore configurazione del delegato per il tuo modello. Ad esempio, --gpu_backend=gl può essere specificato con --use_gpu per misurare l'esecuzione della GPU con OpenGL. L'elenco completo dei parametri delegati supportati è definito nella documentazione dettagliata.

Ecco un esempio di esecuzione per un modello quantizzato con GPU tramite adb:

adb shell /data/local/tmp/benchmark_model \
  --graph=/data/local/tmp/mobilenet_v1_224_quant.tflite \
  --use_gpu=true

Puoi scaricare la versione precompilata di questo strumento per Android, architettura ARM a 64 bit qui (maggiori dettagli).

Accuratezza e correttezza

I delegati in genere eseguono i calcoli con una precisione diversa rispetto alle loro controparti della CPU. Di conseguenza, l'utilizzo di un delegato per l'accelerazione hardware comporta un compromesso (di solito minore) in termini di precisione. Tieni presente che questo non è sempre vero.Ad esempio, poiché la GPU utilizza la precisione in virgola mobile per eseguire modelli quantizzati, potrebbe esserci un leggero miglioramento della precisione (ad es. Miglioramento inferiore all'1% nella classificazione delle immagini ILSVRC.

LiteRT dispone di due tipi di strumenti per misurare la precisione del comportamento di un delegato per un determinato modello: basato sulle attività e indipendente dalle attività. Tutti gli strumenti descritti in questa sezione supportano i parametri di delega avanzata utilizzati dallo strumento di benchmarking della sezione precedente. Tieni presente che le sottosezioni riportate di seguito si concentrano sulla valutazione del delegato (il delegato esegue la stessa operazione della CPU?) anziché sulla valutazione del modello (il modello stesso è adatto all'attività?).

Valutazione basata sulle attività

LiteRT dispone di strumenti per valutare la correttezza di due attività basate su immagini:

I file binari precompilati di questi strumenti (Android, architettura ARM a 64 bit), insieme alla documentazione, sono disponibili qui:

L'esempio seguente mostra la valutazione della classificazione delle immagini con la GPU su Pixel 4:

adb shell /data/local/tmp/run_eval \
  --model_file=/data/local/tmp/mobilenet_quant_v1_224.tflite \
  --ground_truth_images_path=/data/local/tmp/ilsvrc_images \
  --ground_truth_labels=/data/local/tmp/ilsvrc_validation_labels.txt \
  --model_output_labels=/data/local/tmp/model_output_labels.txt \
  --output_file_path=/data/local/tmp/accuracy_output.txt \
  --num_images=0 # Run on all images. \
  --use_gpu=true

L'output previsto è un elenco di metriche Top-K da 1 a 10:

Top-1 Accuracy: 0.733333
Top-2 Accuracy: 0.826667
Top-3 Accuracy: 0.856667
Top-4 Accuracy: 0.87
Top-5 Accuracy: 0.89
Top-6 Accuracy: 0.903333
Top-7 Accuracy: 0.906667
Top-8 Accuracy: 0.913333
Top-9 Accuracy: 0.92
Top-10 Accuracy: 0.923333

Valutazione indipendente dall'attività

Per le attività in cui non esiste uno strumento di valutazione sul dispositivo consolidato o se stai sperimentando modelli personalizzati, LiteRT dispone dello strumento Differenza di inferenza. (Android, binario dell'architettura binaria ARM a 64 bit qui)

Inference Diff confronta l'esecuzione di LiteRT (in termini di latenza e deviazione del valore di output) in due impostazioni:

  • Inferenza della CPU a thread singolo
  • Inferenza definita dall'utente, definita da questi parametri

A questo scopo, lo strumento genera dati gaussiani casuali e li passa attraverso due interpreti TFLite: uno che esegue kernel della CPU a thread singolo e l'altro parametrizzato dagli argomenti dell'utente.

Misura la latenza di entrambi, nonché la differenza assoluta tra i tensori di output di ogni interprete, in base a ogni elemento.

Per un modello con un singolo tensore di output, l'output potrebbe avere il seguente aspetto:

Num evaluation runs: 50
Reference run latency: avg=84364.2(us), std_dev=12525(us)
Test run latency: avg=7281.64(us), std_dev=2089(us)
OutputDiff[0]: avg_error=1.96277e-05, std_dev=6.95767e-06

Ciò significa che per il tensore di output all'indice 0, gli elementi dell'output della CPU differiscono dall'output del delegato in media di 1.96e-05.

Tieni presente che l'interpretazione di questi numeri richiede una conoscenza più approfondita del modello e di ciò che significa ogni tensore di output. Se si tratta di una semplice regressione che determina un qualche tipo di punteggio o incorporamento, la differenza dovrebbe essere bassa (altrimenti si tratta di un errore con il delegato). Tuttavia, output come quello della "classe di rilevamento" dei modelli SSD sono un po' più difficili da interpretare. Ad esempio, potrebbe mostrare una differenza utilizzando questo strumento, ma ciò non significa che ci sia qualcosa di sbagliato nel delegato: considera due classi (fittizie): "TV (ID: 10)", "Monitor (ID:20)". Se un delegato si discosta leggermente dalla verità e mostra il monitor anziché la TV, la differenza di output per questo tensore potrebbe essere pari a 20-10 = 10.