Ottimizza le prestazioni di TensorFlow utilizzando il Profiler

Mantieni tutto organizzato con le raccolte Salva e classifica i contenuti in base alle tue preferenze.

Questa guida mostra come utilizzare gli strumenti disponibili con TensorFlow Profiler per tenere traccia delle prestazioni dei tuoi modelli TensorFlow. Imparerai come capire come si comporta il tuo modello sull'host (CPU), sul dispositivo (GPU) o su una combinazione di host e dispositivi.

La profilazione aiuta a comprendere il consumo di risorse hardware (tempo e memoria) delle varie operazioni (operazioni) TensorFlow nel modello e a risolvere i colli di bottiglia delle prestazioni e, in definitiva, a velocizzare l'esecuzione del modello.

Questa guida ti guiderà attraverso come installare il Profiler, i vari strumenti disponibili, le diverse modalità di raccolta dei dati sulle prestazioni e alcune best practice consigliate per ottimizzare le prestazioni del modello.

Se desideri profilare le prestazioni del tuo modello su Cloud TPU, fai riferimento alla guida Cloud TPU .

Installa i prerequisiti del Profiler e della GPU

Installa il plugin Profiler per TensorBoard con pip. Si noti che il Profiler richiede le ultime versioni di TensorFlow e TensorBoard (>=2.2).

pip install -U tensorboard_plugin_profile

Per eseguire il profilo sulla GPU, devi:

  1. Soddisfa i driver della GPU NVIDIA® e i requisiti CUDA® Toolkit elencati nei requisiti del software di supporto GPU TensorFlow .
  2. Assicurati che l' interfaccia degli strumenti di profilatura NVIDIA® CUDA® (CUPTI) sia presente sul percorso:

    /sbin/ldconfig -N -v $(sed 's/:/ /g' <<< $LD_LIBRARY_PATH) | \
    grep libcupti
    

Se non hai CUPTI nel percorso, anteponi la sua directory di installazione alla variabile di ambiente $LD_LIBRARY_PATH eseguendo:

export LD_LIBRARY_PATH=/usr/local/cuda/extras/CUPTI/lib64:$LD_LIBRARY_PATH

Quindi, eseguire nuovamente il comando ldconfig sopra per verificare che sia stata trovata la libreria CUPTI.

Risolvi i problemi di privilegio

Quando si esegue la profilatura con CUDA® Toolkit in un ambiente Docker o su Linux, potrebbero verificarsi problemi relativi a privilegi CUPTI insufficienti ( CUPTI_ERROR_INSUFFICIENT_PRIVILEGES ). Vai a NVIDIA Developer Docs per saperne di più su come risolvere questi problemi su Linux.

Per risolvere i problemi relativi ai privilegi CUPTI in un ambiente Docker, eseguire

docker run option '--privileged=true'

Strumenti di profilazione

Accedi al Profiler dalla scheda Profilo in TensorBoard, che appare solo dopo aver acquisito alcuni dati del modello.

Il Profiler ha una selezione di strumenti per aiutare con l'analisi delle prestazioni:

  • Pagina Panoramica
  • Analizzatore della pipeline di input
  • Statistiche TensorFlow
  • Visualizzatore di tracce
  • Statistiche del kernel della GPU
  • Strumento profilo di memoria
  • Visualizzatore di baccelli

Pagina panoramica

La pagina di panoramica fornisce una vista di livello superiore delle prestazioni del modello durante un'esecuzione del profilo. La pagina mostra una pagina di panoramica aggregata per il tuo host e tutti i dispositivi e alcuni consigli per migliorare le prestazioni dell'allenamento del modello. Puoi anche selezionare singoli host nel menu a discesa Host.

La pagina panoramica mostra i dati come segue:

Immagine

  • Riepilogo prestazioni : Visualizza un riepilogo di alto livello delle prestazioni del modello. Il riepilogo delle prestazioni si compone di due parti:

    1. Ripartizione del tempo di passaggio: suddivide il tempo di passaggio medio in più categorie in cui viene speso il tempo:

      • Compilation: tempo impiegato per compilare i kernel.
      • Input: tempo impiegato per leggere i dati di input.
      • Output: tempo impiegato per leggere i dati di output.
      • Lancio del kernel: tempo impiegato dall'host per avviare i kernel
      • Tempo di calcolo dell'host..
      • Tempo di comunicazione da dispositivo a dispositivo.
      • Tempo di calcolo sul dispositivo.
      • Tutti gli altri, incluso l'overhead di Python.
    2. Precisione di calcolo del dispositivo: segnala la percentuale del tempo di calcolo del dispositivo che utilizza calcoli a 16 e 32 bit.

  • Grafico del tempo di passaggio : Visualizza un grafico del tempo di passaggio del dispositivo (in millisecondi) su tutti i passaggi campionati. Ogni passaggio è suddiviso in più categorie (con colori diversi) in cui viene trascorso il tempo. L'area rossa corrisponde alla parte del tempo di passaggio in cui i dispositivi sono rimasti inattivi in ​​​​attesa di dati di input dall'host. L'area verde mostra per quanto tempo il dispositivo stava effettivamente funzionando.

  • Prime 10 operazioni TensorFlow sul dispositivo (ad es. GPU) : mostra le operazioni sul dispositivo che sono state eseguite più a lungo.

    Ogni riga mostra il tempo personale di un'operazione (come percentuale di tempo impiegato da tutte le operazioni), il tempo cumulativo, la categoria e il nome.

  • Ambiente di esecuzione : Visualizza un riepilogo di alto livello dell'ambiente di esecuzione del modello, tra cui:

    • Numero di host utilizzati.
    • Tipo di dispositivo (GPU/TPU).
    • Numero di core del dispositivo.
  • Raccomandazione per il passaggio successivo : segnala quando un modello è vincolato all'input e consiglia gli strumenti che è possibile utilizzare per individuare e risolvere i colli di bottiglia delle prestazioni del modello.

Analizzatore della pipeline di ingresso

Quando un programma TensorFlow legge i dati da un file, inizia nella parte superiore del grafico TensorFlow in modo pipeline. Il processo di lettura è suddiviso in più fasi di elaborazione dati collegate in serie, dove l'uscita di una fase è l'input per quella successiva. Questo sistema di lettura dei dati è chiamato pipeline di input .

Una tipica pipeline per la lettura dei record dai file prevede le fasi seguenti:

  1. Lettura di file.
  2. Preelaborazione dei file (opzionale).
  3. Trasferimento di file dall'host al dispositivo.

Una pipeline di input inefficiente può rallentare notevolmente l'applicazione. Un'applicazione è considerata vincolata all'input quando trascorre una parte significativa del tempo nella pipeline di input. Usa le informazioni ottenute dall'analizzatore della pipeline di input per capire dove la pipeline di input è inefficiente.

L'analizzatore della pipeline di input ti dice immediatamente se il tuo programma è associato all'input e ti guida attraverso l'analisi lato dispositivo e host per eseguire il debug dei colli di bottiglia delle prestazioni in qualsiasi fase della pipeline di input.

Consulta le linee guida sulle prestazioni della pipeline di input per le best practice consigliate per ottimizzare le pipeline di input dei dati.

Dashboard della pipeline di input

Per aprire l'analizzatore della pipeline di input, seleziona Profile , quindi seleziona input_pipeline_analyzer dal menu a discesa Strumenti .

Immagine

La dashboard contiene tre sezioni:

  1. Riepilogo : riassume la pipeline di input complessiva con informazioni sul fatto che l'applicazione sia associata all'input e, in tal caso, di quanto.
  2. Analisi lato dispositivo : visualizza risultati dettagliati dell'analisi lato dispositivo, inclusi il tempo di passaggio del dispositivo e l'intervallo di tempo trascorso dal dispositivo in attesa di dati di input tra i core a ogni passaggio.
  3. Analisi lato host : mostra un'analisi dettagliata sul lato host, inclusa una ripartizione del tempo di elaborazione dell'input sull'host.

Riepilogo della pipeline di input

Il riepilogo segnala se il programma è vincolato all'input presentando la percentuale di tempo impiegato dal dispositivo in attesa dell'input dall'host. Se si utilizza una pipeline di input standard che è stata strumentata, lo strumento segnala dove viene spesa la maggior parte del tempo di elaborazione dell'input.

Analisi lato dispositivo

L'analisi lato dispositivo fornisce informazioni dettagliate sul tempo trascorso sul dispositivo rispetto all'host e sul tempo trascorso dal dispositivo in attesa dei dati di input dall'host.

  1. Tempo di passaggio tracciato rispetto al numero di passaggio : Visualizza un grafico del tempo di passaggio del dispositivo (in millisecondi) su tutti i passaggi campionati. Ogni passaggio è suddiviso in più categorie (con colori diversi) in cui viene trascorso il tempo. L'area rossa corrisponde alla parte del tempo di passaggio in cui i dispositivi sono rimasti inattivi in ​​​​attesa di dati di input dall'host. L'area verde mostra per quanto tempo il dispositivo stava effettivamente funzionando.
  2. Statistiche del tempo di passaggio : riporta la media, la deviazione standard e l'intervallo ([minimo, massimo]) del tempo di passaggio del dispositivo.

Analisi lato host

L'analisi lato host riporta una suddivisione del tempo di elaborazione dell'input (il tempo speso per le operazioni API tf.data ) sull'host in diverse categorie:

  • Lettura di dati da file su richiesta : tempo dedicato alla lettura di dati da file senza memorizzazione nella cache, prelettura e interleaving.
  • Lettura anticipata dei dati dai file : tempo dedicato alla lettura dei file, inclusi memorizzazione nella cache, prelettura e interleaving.
  • Preelaborazione dei dati : tempo dedicato alle operazioni di preelaborazione, come la decompressione dell'immagine.
  • Accodamento dei dati da trasferire al dispositivo : tempo impiegato per inserire i dati in una coda di alimentazione prima di trasferirli al dispositivo.

Espandi Statistiche operazioni di input per esaminare le statistiche per le singole operazioni di input e le relative categorie suddivise per tempo di esecuzione.

Immagine

Apparirà una tabella dei dati di origine con ogni voce contenente le seguenti informazioni:

  1. Input Op : Mostra il nome dell'operazione TensorFlow dell'operazione di input.
  2. Conteggio : mostra il numero totale di istanze di esecuzione delle operazioni durante il periodo di profilatura.
  3. Tempo totale (in ms) : mostra la somma cumulativa del tempo trascorso su ciascuna di queste istanze.
  4. Tempo totale % : mostra il tempo totale speso per un'operazione come frazione del tempo totale speso per l'elaborazione dell'input.
  5. Tempo totale di autonomia (in ms) : mostra la somma cumulativa del tempo di autonomia trascorso su ciascuna di queste istanze. Il tempo personale qui misura il tempo trascorso all'interno del corpo della funzione, escluso il tempo trascorso nella funzione che chiama.
  6. % tempo totale auto . Mostra il tempo totale di autonomia come frazione del tempo totale impiegato per l'elaborazione dell'input.
  7. Categoria . Mostra la categoria di elaborazione dell'input op.

Statistiche TensorFlow

Lo strumento TensorFlow Stats mostra le prestazioni di ogni operazione TensorFlow eseguita sull'host o sul dispositivo durante una sessione di profilatura.

Immagine

Lo strumento visualizza le informazioni sulle prestazioni in due riquadri:

  • Il riquadro superiore mostra fino a quattro grafici a torta:

    1. La distribuzione del tempo di autoesecuzione di ogni operazione sull'host.
    2. La distribuzione del tempo di autoesecuzione di ogni tipo di operazione sull'host.
    3. La distribuzione del tempo di autoesecuzione di ciascuna operazione sul dispositivo.
    4. La distribuzione del tempo di autoesecuzione di ogni tipo di operazione sul dispositivo.
  • Il riquadro inferiore mostra una tabella che riporta i dati sulle operazioni di TensorFlow con una riga per ciascuna operazione e una colonna per ogni tipo di dati (ordina le colonne facendo clic sull'intestazione della colonna). Fare clic sul pulsante Esporta come CSV sul lato destro del riquadro superiore per esportare i dati da questa tabella come file CSV.

    Notare che:

    • Se qualche operazione ha operazioni figlio:

      • Il tempo totale "accumulato" di un'operazione include il tempo trascorso all'interno delle operazioni figlio.
      • Il tempo "auto" totale di un'operazione non include il tempo trascorso all'interno delle operazioni figlio.
    • Se un'operazione viene eseguita sull'host:

      • La percentuale del tempo personale totale sul dispositivo sostenuto dall'operazione sarà 0.
      • La percentuale cumulativa del tempo personale totale sul dispositivo fino a questa operazione inclusa sarà 0.
    • Se un'operazione viene eseguita sul dispositivo:

      • La percentuale del tempo libero totale sull'host sostenuto da questa operazione sarà 0.
      • La percentuale cumulativa del tempo libero totale sull'host fino a questa operazione inclusa sarà 0.

Puoi scegliere di includere o escludere il tempo di inattività nei grafici a torta e nella tabella.

Visualizzatore di tracce

Il visualizzatore di tracce mostra una sequenza temporale che mostra:

  • Durata delle operazioni eseguite dal tuo modello TensorFlow
  • Quale parte del sistema (host o dispositivo) ha eseguito un'op. In genere, l'host esegue operazioni di input, preelabora i dati di training e li trasferisce al dispositivo, mentre il dispositivo esegue il training del modello effettivo

Il visualizzatore di tracce consente di identificare i problemi di prestazioni nel modello, quindi di adottare le misure per risolverli. Ad esempio, a un livello elevato, è possibile identificare se l'input o l'addestramento del modello richiedono la maggior parte del tempo. Eseguendo il drill-down, puoi identificare quali operazioni richiedono più tempo per essere eseguite. Tieni presente che il visualizzatore di tracce è limitato a 1 milione di eventi per dispositivo.

Interfaccia visualizzatore di tracce

Quando si apre il visualizzatore di tracce, viene visualizzata la visualizzazione della corsa più recente:

Immagine

Questa schermata contiene i seguenti elementi principali:

  1. Riquadro sequenza temporale : mostra le operazioni eseguite nel tempo dal dispositivo e dall'host.
  2. Riquadro dei dettagli : mostra informazioni aggiuntive per le operazioni selezionate nel riquadro della sequenza temporale.

Il riquadro Timeline contiene i seguenti elementi:

  1. Barra in alto: contiene vari controlli ausiliari.
  2. Asse del tempo : mostra il tempo relativo all'inizio della traccia.
  3. Etichette di sezioni e tracce : ogni sezione contiene più tracce e ha un triangolo a sinistra su cui puoi fare clic per espandere e comprimere la sezione. C'è una sezione per ogni elemento di elaborazione nel sistema.
  4. Selettore strumenti : contiene vari strumenti per interagire con il visualizzatore di tracce come Zoom, Panoramica, Seleziona e Temporizzazione. Utilizzare lo strumento Tempistica per contrassegnare un intervallo di tempo.
  5. Eventi : mostrano il tempo durante il quale è stata eseguita un'operazione o la durata dei meta-eventi, come le fasi di formazione.
Sezioni e tracce

Il visualizzatore di tracce contiene le seguenti sezioni:

  • Una sezione per ogni nodo del dispositivo , etichettata con il numero del chip del dispositivo e il nodo del dispositivo all'interno del chip (ad esempio, /device:GPU:0 (pid 0) ). Ciascuna sezione del nodo del dispositivo contiene le seguenti tracce:
    • Passaggio : mostra la durata dei passaggi di formazione in esecuzione sul dispositivo
    • TensorFlow Ops : mostra le operazioni eseguite sul dispositivo
    • XLA Ops : mostra le operazioni XLA (operazioni) eseguite sul dispositivo se XLA è il compilatore utilizzato (ogni operazione TensorFlow viene convertita in una o più operazioni XLA. Il compilatore XLA traduce le operazioni XLA in codice che viene eseguito sul dispositivo).
  • Una sezione per i thread in esecuzione sulla CPU della macchina host, denominata "Host Threads" . La sezione contiene una traccia per ogni thread della CPU. Tieni presente che puoi ignorare le informazioni visualizzate accanto alle etichette delle sezioni.
Eventi

Gli eventi all'interno della sequenza temporale vengono visualizzati in diversi colori; i colori stessi non hanno un significato specifico.

Il visualizzatore di tracce può anche visualizzare tracce di chiamate di funzioni Python nel programma TensorFlow. Se usi l'API tf.profiler.experimental.start , puoi abilitare la traccia Python usando ProfilerOptions namedtuple quando avvii la profilatura. In alternativa, se si utilizza la modalità di campionamento per la creazione di profili, è possibile selezionare il livello di traccia utilizzando le opzioni a discesa nella finestra di dialogo Acquisisci profilo .

Immagine

Statistiche del kernel della GPU

Questo strumento mostra le statistiche sulle prestazioni e l'operazione di origine per ogni kernel con accelerazione GPU.

Immagine

Lo strumento visualizza le informazioni in due riquadri:

  • Il riquadro superiore mostra un grafico a torta che mostra i kernel CUDA con il tempo totale trascorso più alto.

  • Il riquadro inferiore mostra una tabella con i seguenti dati per ogni coppia univoca del kernel-op:

    • Una classifica in ordine decrescente della durata totale della GPU trascorsa raggruppata per coppia kernel-op.
    • Il nome del kernel avviato.
    • Il numero di registri GPU utilizzati dal kernel.
    • La dimensione totale della memoria condivisa (statica + condivisa dinamica) utilizzata in byte.
    • La dimensione del blocco espressa come blockDim.x, blockDim.y, blockDim.z .
    • Le dimensioni della griglia espresse come gridDim.x, gridDim.y, gridDim.z .
    • Se l'operazione è idonea a utilizzare Tensor Cores .
    • Se il kernel contiene istruzioni Tensor Core.
    • Il nome dell'operazione che ha lanciato questo kernel.
    • Il numero di occorrenze di questa coppia kernel-op.
    • Il tempo totale trascorso dalla GPU in microsecondi.
    • Il tempo medio trascorso dalla GPU in microsecondi.
    • Il tempo GPU minimo trascorso in microsecondi.
    • Il tempo GPU massimo trascorso in microsecondi.

Strumento profilo di memoria

Lo strumento Profilo memoria monitora l'utilizzo della memoria del dispositivo durante l'intervallo di profilatura. Puoi utilizzare questo strumento per:

  • Esegui il debug dei problemi di memoria insufficiente (OOM) individuando il picco di utilizzo della memoria e l'allocazione di memoria corrispondente alle operazioni di TensorFlow. Puoi anche eseguire il debug dei problemi OOM che possono sorgere quando esegui l'inferenza multi-tenancy .
  • Debug dei problemi di frammentazione della memoria.

Lo strumento del profilo di memoria visualizza i dati in tre sezioni:

  1. Riepilogo del profilo di memoria
  2. Grafico della sequenza temporale della memoria
  3. Tabella di ripartizione della memoria

Riepilogo del profilo di memoria

Questa sezione mostra un riepilogo di alto livello del profilo di memoria del programma TensorFlow come mostrato di seguito:

Il riepilogo del profilo di memoria ha sei campi:

  1. ID memoria : elenco a discesa che elenca tutti i sistemi di memoria del dispositivo disponibili. Seleziona il sistema di memoria che desideri visualizzare dal menu a discesa.
  2. #Allocation : il numero di allocazioni di memoria effettuate durante l'intervallo di profilatura.
  3. #Deallocation : il numero di deallocazioni di memoria nell'intervallo di profilatura
  4. Capacità di memoria : la capacità totale (in GiB) del sistema di memoria selezionato.
  5. Peak Heap Usage : il picco di utilizzo della memoria (in GiB) dall'avvio dell'esecuzione del modello.
  6. Peak Memory Usage : il picco di utilizzo della memoria (in GiB) nell'intervallo di profilatura. Questo campo contiene i seguenti sottocampi:
    1. Timestamp : il timestamp di quando si è verificato il picco di utilizzo della memoria sul grafico della sequenza temporale.
    2. Prenotazione dello stack : quantità di memoria riservata nello stack (in GiB).
    3. Allocazione dell'heap: quantità di memoria allocata nell'heap (in GiB).
    4. Memoria libera : quantità di memoria libera (in GiB). La capacità di memoria è la somma totale della prenotazione dello stack, dell'allocazione dell'heap e della memoria libera.
    5. Frammentazione : la percentuale di frammentazione (più bassa è migliore). Viene calcolato come percentuale di (1 - Size of the largest chunk of free memory / Total free memory) .

Grafico della sequenza temporale della memoria

Questa sezione mostra un grafico dell'utilizzo della memoria (in GiB) e la percentuale di frammentazione rispetto al tempo (in ms).

Immagine

L'asse X rappresenta la sequenza temporale (in ms) dell'intervallo di profilatura. L'asse Y a sinistra rappresenta l'utilizzo della memoria (in GiB) e l'asse Y a destra rappresenta la percentuale di frammentazione. In ogni momento sull'asse X, la memoria totale è suddivisa in tre categorie: stack (in rosso), heap (in arancione) e free (in verde). Passa il mouse su un timestamp specifico per visualizzare i dettagli sugli eventi di allocazione/distribuzione della memoria a quel punto come di seguito:

Immagine

La finestra a comparsa mostra le seguenti informazioni:

  • timestamp(ms) : la posizione dell'evento selezionato sulla timeline.
  • event : il tipo di evento (allocazione o deallocazione).
  • request_size(GiBs) : la quantità di memoria richiesta. Questo sarà un numero negativo per gli eventi di deallocazione.
  • allocation_size(GiBs) : la quantità effettiva di memoria allocata. Questo sarà un numero negativo per gli eventi di deallocazione.
  • tf_op : L'operazione TensorFlow che richiede l'allocazione/deallocazione.
  • step_id : la fase di addestramento in cui si è verificato questo evento.
  • region_type : il tipo di entità dati a cui è destinata questa memoria allocata. I valori possibili sono temp per temporanei, output per attivazioni e gradienti e persist / dynamic per pesi e costanti.
  • data_type : il tipo di elemento tensore (ad es. uint8 per intero senza segno a 8 bit).
  • tensor_shape : la forma del tensore allocato/deallocato.
  • memory_in_use(GiBs) : la memoria totale in uso in questo momento.

Tabella di ripartizione della memoria

Questa tabella mostra le allocazioni di memoria attive nel punto di picco di utilizzo della memoria nell'intervallo di profilatura.

Immagine

C'è una riga per ogni TensorFlow Op e ogni riga ha le seguenti colonne:

  • Op Name : Il nome del TensorFlow op.
  • Dimensione allocazione (GiBs) : la quantità totale di memoria allocata a questa op.
  • Dimensione richiesta (GiB) : la quantità totale di memoria richiesta per questa op.
  • Occorrenze : il numero di assegnazioni per questa op.
  • Tipo di regione : il tipo di entità di dati a cui si riferisce questa memoria allocata. I valori possibili sono temp per temporanei, output per attivazioni e gradienti e persist / dynamic per pesi e costanti.
  • Tipo di dati : il tipo di elemento tensore.
  • Shape : La forma dei tensori allocati.

Visualizzatore di baccelli

Lo strumento Pod Viewer mostra la suddivisione di una fase di formazione in tutti i lavoratori.

Immagine

  • Il riquadro superiore ha un dispositivo di scorrimento per la selezione del numero di passaggio.
  • Il riquadro inferiore visualizza un istogramma in pila. Questa è una vista di alto livello di categorie di tempi di passaggio scomposte poste l'una sull'altra. Ogni colonna in pila rappresenta un lavoratore univoco.
  • Quando passi il mouse su una colonna impilata, la carta sul lato sinistro mostra maggiori dettagli sulla suddivisione dei passaggi.

tf.analisi del collo di bottiglia dei dati

Lo strumento di analisi dei colli di bottiglia tf.data rileva automaticamente i colli di bottiglia nelle pipeline di input di tf.data nel programma e fornisce consigli su come risolverli. Funziona con qualsiasi programma che utilizzi tf.data indipendentemente dalla piattaforma (CPU/GPU/TPU). La sua analisi e le sue raccomandazioni si basano su questa guida .

Rileva un collo di bottiglia seguendo questi passaggi:

  1. Trova l'host con il maggior numero di input.
  2. Trova l'esecuzione più lenta di una pipeline di input tf.data .
  3. Ricostruisci il grafico della pipeline di input dalla traccia del profiler.
  4. Trova il percorso critico nel grafico della pipeline di input.
  5. Identifica la trasformazione più lenta sul percorso critico come collo di bottiglia.

L'interfaccia utente è suddivisa in tre sezioni: Riepilogo dell'analisi delle prestazioni , Riepilogo di tutte le pipeline di input e Grafico della pipeline di input.

Riepilogo dell'analisi delle prestazioni

Immagine

Questa sezione fornisce la sintesi dell'analisi. Segnala le pipeline di input tf.data lente rilevate nel profilo. Questa sezione mostra anche l'host con più input associato e la relativa pipeline di input più lenta con la latenza massima. Soprattutto, identifica quale parte della pipeline di input è il collo di bottiglia e come risolverlo. Le informazioni sul collo di bottiglia vengono fornite con il tipo di iteratore e il relativo nome lungo.

Come leggere il nome lungo dell'iteratore tf.data

Un nome lungo è formattato come Iterator::<Dataset_1>::...::<Dataset_n> . Nel nome lungo, <Dataset_n> corrisponde al tipo di iteratore e gli altri dataset nel nome lungo rappresentano le trasformazioni a valle.

Ad esempio, considera il seguente set di dati della pipeline di input:

dataset = tf.data.Dataset.range(10).map(lambda x: x).repeat(2).batch(5)

I nomi lunghi per gli iteratori del set di dati sopra saranno:

Tipo di iteratore Nome lungo
Gamma Iteratore::Lotto::Ripeti::Mappa::Intervallo
Carta geografica Iteratore::Lotto::Ripeti::Mappa
Ripetere Iteratore::Lotto::Ripeti
Lotto Iteratore::Lotto

Riepilogo di tutte le pipeline di input

Immagine

Questa sezione fornisce il riepilogo di tutte le pipeline di input in tutti gli host. In genere è presente una pipeline di input. Quando si utilizza la strategia di distribuzione, esiste una pipeline di input dell'host che esegue il codice tf.data del programma e più pipeline di input del dispositivo che recuperano i dati dalla pipeline di input dell'host e li trasferiscono ai dispositivi.

Per ogni pipeline di input, mostra le statistiche del suo tempo di esecuzione. Una chiamata viene conteggiata come lenta se impiega più di 50 μs.

Grafico della pipeline di input

Immagine

Questa sezione mostra il grafico della pipeline di input con le informazioni sul tempo di esecuzione. Puoi utilizzare "Host" e "Input Pipeline" per scegliere quale host e quale pipeline di input visualizzare. Le esecuzioni della pipeline di input sono ordinate in base al tempo di esecuzione in ordine decrescente che puoi scegliere utilizzando il menu a discesa Rank .

Immagine

I nodi sul percorso critico hanno contorni in grassetto. Il nodo del collo di bottiglia, ovvero il nodo con il tempo automatico più lungo sul percorso critico, ha un contorno rosso. Gli altri nodi non critici hanno contorni tratteggiati grigi.

In ogni nodo, Start Time indica l'ora di inizio dell'esecuzione. Lo stesso nodo può essere eseguito più volte, ad esempio, se è presente un'operazione Batch nella pipeline di input. Se viene eseguito più volte, è l'ora di inizio della prima esecuzione.

La durata totale è il tempo di parete dell'esecuzione. Se viene eseguito più volte, è la somma dei tempi di parete di tutte le esecuzioni.

Self Time è il tempo totale senza il tempo sovrapposto con i suoi immediati nodi figlio.

"# Chiamate" è il numero di volte in cui viene eseguita la pipeline di input.

Raccogli i dati sulle prestazioni

TensorFlow Profiler raccoglie le attività host e le tracce GPU del tuo modello TensorFlow. È possibile configurare il Profiler per raccogliere i dati sulle prestazioni tramite la modalità programmatica o la modalità di campionamento.

API di profilazione

È possibile utilizzare le seguenti API per eseguire la profilazione.

  • Modalità programmatica utilizzando TensorBoard Keras Callback ( tf.keras.callbacks.TensorBoard )

    # Profile from batches 10 to 15
    tb_callback = tf.keras.callbacks.TensorBoard(log_dir=log_dir,
                                                 profile_batch='10, 15')
    
    # Train the model and use the TensorBoard Keras callback to collect
    # performance profiling data
    model.fit(train_data,
              steps_per_epoch=20,
              epochs=5,
              callbacks=[tb_callback])
    
  • Modalità programmatica tramite l'API della funzione tf.profiler

    tf.profiler.experimental.start('logdir')
    # Train the model here
    tf.profiler.experimental.stop()
    
  • Modalità programmatica utilizzando il gestore del contesto

    with tf.profiler.experimental.Profile('logdir'):
        # Train the model here
        pass
    

  • Modalità di campionamento: esegui la profilatura su richiesta utilizzando tf.profiler.experimental.server.start per avviare un server gRPC con l'esecuzione del modello TensorFlow. Dopo aver avviato il server gRPC e aver eseguito il modello, puoi acquisire un profilo tramite il pulsante Cattura profilo nel plug-in del profilo TensorBoard. Usa lo script nella sezione Install profiler sopra per avviare un'istanza TensorBoard se non è già in esecuzione.

    Come esempio,

    # Start a profiler server before your model runs.
    tf.profiler.experimental.server.start(6009)
    # (Model code goes here).
    #  Send a request to the profiler server to collect a trace of your model.
    tf.profiler.experimental.client.trace('grpc://localhost:6009',
                                          'gs://your_tb_logdir', 2000)
    

    Un esempio per la profilazione di più lavoratori:

    # E.g. your worker IP addresses are 10.0.0.2, 10.0.0.3, 10.0.0.4, and you
    # would like to profile for a duration of 2 seconds.
    tf.profiler.experimental.client.trace(
        'grpc://10.0.0.2:8466,grpc://10.0.0.3:8466,grpc://10.0.0.4:8466',
        'gs://your_tb_logdir',
        2000)
    

Utilizzare la finestra di dialogo Cattura profilo per specificare:

  • Un elenco delimitato da virgole di URL del servizio profilo o nomi TPU.
  • Una durata di profilazione.
  • Il livello di traccia delle chiamate di funzioni di dispositivo, host e Python.
  • Quante volte si desidera che il Profiler riprovi ad acquisire i profili se all'inizio non riesce.

Profilazione di cicli di formazione personalizzati

Per profilare cicli di addestramento personalizzati nel codice TensorFlow, strumenta il ciclo di addestramento con l'API tf.profiler.experimental.Trace per contrassegnare i limiti dei passaggi per il Profiler.

L'argomento name viene utilizzato come prefisso per i nomi dei passaggi, l'argomento della parola chiave step_num viene aggiunto ai nomi dei passaggi e l'argomento della parola chiave _r fa sì che questo evento di traccia venga elaborato come evento del passaggio dal Profiler.

Come esempio,

for step in range(NUM_STEPS):
    with tf.profiler.experimental.Trace('train', step_num=step, _r=1):
        train_data = next(dataset)
        train_step(train_data)

Ciò consentirà l'analisi delle prestazioni basata sui passaggi del Profiler e farà sì che gli eventi dei passaggi vengano visualizzati nel visualizzatore di tracce.

Assicurati di includere l'iteratore del set di dati nel contesto tf.profiler.experimental.Trace per un'analisi accurata della pipeline di input.

Il frammento di codice di seguito è un anti-pattern:

for step, train_data in enumerate(dataset):
    with tf.profiler.experimental.Trace('train', step_num=step, _r=1):
        train_step(train_data)

Profilazione dei casi d'uso

Il profiler copre una serie di casi d'uso lungo quattro diversi assi. Alcune delle combinazioni sono attualmente supportate e altre verranno aggiunte in futuro. Alcuni dei casi d'uso sono:

  • Profilazione locale e remota : questi sono due modi comuni per configurare l'ambiente di profilazione. Nella profilazione locale, l'API di profilatura viene chiamata sulla stessa macchina che il tuo modello sta eseguendo, ad esempio una workstation locale con GPU. Nella profilazione remota, l'API di profilatura viene chiamata su una macchina diversa da quella su cui è in esecuzione il modello, ad esempio su una Cloud TPU.
  • Profilazione di più lavoratori : è possibile profilare più macchine quando si utilizzano le capacità di formazione distribuita di TensorFlow.
  • Piattaforma hardware : profila CPU, GPU e TPU.

La tabella seguente fornisce una rapida panoramica dei casi d'uso supportati da TensorFlow menzionati sopra:

API di profilazione Locale A distanza Più lavoratori Piattaforme hardware
Richiamata TensorBoard Keras Supportato Non supportato Non supportato CPU, GPU
tf.profiler.experimental API di avvio/arresto Supportato Non supportato Non supportato CPU, GPU
tf.profiler.experimental client.trace API Supportato Supportato Supportato CPU, GPU, TPU
API di gestione del contesto Supportato Non supportato Non supportato CPU, GPU

Migliori pratiche per prestazioni ottimali del modello

Utilizzare i seguenti consigli, a seconda dei casi, per i propri modelli TensorFlow per ottenere prestazioni ottimali.

In generale, esegui tutte le trasformazioni sul dispositivo e assicurati di utilizzare l'ultima versione compatibile di librerie come cuDNN e Intel MKL per la tua piattaforma.

Ottimizza la pipeline dei dati di input

Utilizza i dati di [#input_pipeline_analyzer] per ottimizzare la pipeline di input dei dati. Un'efficiente pipeline di input dei dati può migliorare drasticamente la velocità di esecuzione del modello riducendo i tempi di inattività del dispositivo. Prova a incorporare le best practice dettagliate nella Guida all'API tf.data per prestazioni migliori e di seguito per rendere più efficiente la pipeline di input dei dati.

  • In generale, la parallelizzazione di tutte le operazioni che non devono essere eseguite in sequenza può ottimizzare in modo significativo la pipeline di input dei dati.

  • In molti casi, è utile modificare l'ordine di alcune chiamate o ottimizzare gli argomenti in modo che funzioni al meglio per il proprio modello. Durante l'ottimizzazione della pipeline dei dati di input, eseguire il benchmark solo del caricatore di dati senza i passaggi di training e backpropagation per quantificare l'effetto delle ottimizzazioni in modo indipendente.

  • Prova a eseguire il tuo modello con dati sintetici per verificare se la pipeline di input è un collo di bottiglia delle prestazioni.

  • Usa tf.data.Dataset.shard per l'addestramento multi-GPU. Assicurati di eseguire lo shard molto presto nel ciclo di input per evitare riduzioni del throughput. Quando si lavora con TFRecords, assicurarsi di dividere l'elenco di TFRecord e non il contenuto di TFRecords.

  • Parallelizza diverse operazioni impostando dinamicamente il valore di num_parallel_calls usando tf.data.AUTOTUNE .

  • Prendi in considerazione la possibilità di limitare l'utilizzo di tf.data.Dataset.from_generator poiché è più lento rispetto alle operazioni di TensorFlow pure.

  • Considerare di limitare l'utilizzo di tf.py_function poiché non può essere serializzato e non è supportato per l'esecuzione in TensorFlow distribuito.

  • Utilizzare tf.data.Options per controllare le ottimizzazioni statiche nella pipeline di input.

Leggi anche la guida all'analisi delle prestazioni di tf.data per ulteriori indicazioni sull'ottimizzazione della pipeline di input.

Ottimizza l'aumento dei dati

Quando lavori con i dati dell'immagine, rendi più efficiente l'aumento dei dati eseguendo il cast a diversi tipi di dati dopo aver applicato trasformazioni spaziali, come capovolgimento, ritaglio, rotazione, ecc.

Usa NVIDIA® DALI

In alcuni casi, ad esempio quando si dispone di un sistema con un rapporto GPU/CPU elevato, tutte le ottimizzazioni di cui sopra potrebbero non essere sufficienti per eliminare i colli di bottiglia nel caricatore di dati causati dalle limitazioni dei cicli della CPU.

Se utilizzi GPU NVIDIA® per applicazioni di visione artificiale e di deep learning audio, prendi in considerazione l'utilizzo della libreria di caricamento dati ( DALI ) per accelerare la pipeline di dati.

Consulta la documentazione NVIDIA® DALI: Operations per un elenco delle operazioni DALI supportate.

Usa threading ed esecuzione parallela

Esegui operazioni su più thread della CPU con l'API tf.config.threading per eseguirli più velocemente.

TensorFlow imposta automaticamente il numero di thread di parallelismo per impostazione predefinita. Il pool di thread disponibile per l'esecuzione delle operazioni TensorFlow dipende dal numero di thread della CPU disponibili.

Controlla la velocità parallela massima per una singola operazione utilizzando tf.config.threading.set_intra_op_parallelism_threads . Nota che se esegui più operazioni in parallelo, condivideranno tutte il pool di thread disponibile.

Se hai operazioni indipendenti non bloccanti (operazioni senza percorso diretto tra di loro sul grafico), usa tf.config.threading.set_inter_op_parallelism_threads per eseguirle contemporaneamente usando il pool di thread disponibile.

Varie

Quando si lavora con modelli più piccoli su GPU NVIDIA®, è possibile impostare tf.compat.v1.ConfigProto.force_gpu_compatible=True per forzare l'allocazione di tutti i tensori della CPU con la memoria bloccata CUDA per dare un notevole impulso alle prestazioni del modello. Tuttavia, prestare attenzione durante l'utilizzo di questa opzione per modelli sconosciuti/molto grandi poiché ciò potrebbe influire negativamente sulle prestazioni dell'host (CPU).

Migliora le prestazioni del dispositivo

Segui le best practice dettagliate qui e nella guida all'ottimizzazione delle prestazioni della GPU per ottimizzare le prestazioni del modello TensorFlow sul dispositivo.

Se utilizzi GPU NVIDIA, registra l'utilizzo della GPU e della memoria in un file CSV eseguendo:

nvidia-smi
--query-gpu=utilization.gpu,utilization.memory,memory.total,
memory.free,memory.used --format=csv

Configura il layout dei dati

Quando si lavora con dati che contengono informazioni sul canale (come le immagini), ottimizzare il formato del layout dei dati per preferire i canali per ultimi (NHWC su NCHW).

I formati di dati dell'ultimo canale migliorano l'utilizzo del Tensor Core e forniscono miglioramenti significativi delle prestazioni soprattutto nei modelli convoluzionali quando accoppiati con AMP. I layout dei dati NCHW possono ancora essere gestiti da Tensor Core, ma introducono un sovraccarico aggiuntivo a causa delle operazioni di trasposizione automatica.

Puoi ottimizzare il layout dei dati per preferire i layout NHWC impostando data_format="channels_last" per livelli come tf.keras.layers.Conv2D , tf.keras.layers.Conv3D e tf.keras.layers.RandomRotation .

Usa tf.keras.backend.set_image_data_format per impostare il formato di layout dei dati predefinito per l'API di backend Keras.

Massimizza la cache L2

When working with NVIDIA® GPUs, execute the code snippet below before the training loop to max out the L2 fetch granularity to 128 bytes.

import ctypes

_libcudart = ctypes.CDLL('libcudart.so')
# Set device limit on the current device
# cudaLimitMaxL2FetchGranularity = 0x05
pValue = ctypes.cast((ctypes.c_int*1)(), ctypes.POINTER(ctypes.c_int))
_libcudart.cudaDeviceSetLimit(ctypes.c_int(0x05), ctypes.c_int(128))
_libcudart.cudaDeviceGetLimit(pValue, ctypes.c_int(0x05))
assert pValue.contents.value == 128

Configure GPU thread usage

The GPU thread mode decides how GPU threads are used.

Set the thread mode to gpu_private to make sure that preprocessing does not steal all the GPU threads. This will reduce the kernel launch delay during training. You can also set the number of threads per GPU. Set these values using environment variables.

import os

os.environ['TF_GPU_THREAD_MODE']='gpu_private'
os.environ['TF_GPU_THREAD_COUNT']='1'

Configure GPU memory options

In general, increase the batch size and scale the model to better utilize GPUs and get higher throughput. Note that increasing the batch size will change the model's accuracy so the model needs to be scaled by tuning hyperparameters like the learning rate to meet the target accuracy.

Also, use tf.config.experimental.set_memory_growth to allow GPU memory to grow to prevent all the available memory from being fully allocated to ops that require only a fraction of the memory. This allows other processes which consume GPU memory to run on the same device.

To learn more, check out the Limiting GPU memory growth guidance in the GPU guide to learn more.

Miscellaneous

  • Increase the training mini-batch size (number of training samples used per device in one iteration of the training loop) to the maximum amount that fits without an out of memory (OOM) error on the GPU. Increasing the batch size impacts the model's accuracy—so make sure you scale the model by tuning hyperparameters to meet the target accuracy.

  • Disable reporting OOM errors during tensor allocation in production code. Set report_tensor_allocations_upon_oom=False in tf.compat.v1.RunOptions .

  • For models with convolution layers, remove bias addition if using batch normalization. Batch normalization shifts values by their mean and this removes the need to have a constant bias term.

  • Use TF Stats to find out how efficiently on-device ops run.

  • Use tf.function to perform computations and optionally, enable the jit_compile=True flag ( tf.function(jit_compile=True ). To learn more, go to Use XLA tf.function .

  • Minimize host Python operations between steps and reduce callbacks. Calculate metrics every few steps instead of at every step.

  • Keep the device compute units busy.

  • Send data to multiple devices in parallel.

  • Consider using 16-bit numerical representations , such as fp16 —the half-precision floating point format specified by IEEE—or the Brain floating-point bfloat16 format.

Additional resources

Known limitations

Profiling multiple GPUs on TensorFlow 2.2 and TensorFlow 2.3

TensorFlow 2.2 and 2.3 support multiple GPU profiling for single host systems only; multiple GPU profiling for multi-host systems is not supported. To profile multi-worker GPU configurations, each worker has to be profiled independently. From TensorFlow 2.4 multiple workers can be profiled using the tf.profiler.experimental.client.trace API.

CUDA® Toolkit 10.2 or later is required to profile multiple GPUs. As TensorFlow 2.2 and 2.3 support CUDA® Toolkit versions only up to 10.1, you need to create symbolic links to libcudart.so.10.1 and libcupti.so.10.1 :

sudo ln -s /usr/local/cuda/lib64/libcudart.so.10.2 /usr/local/cuda/lib64/libcudart.so.10.1
sudo ln -s /usr/local/cuda/extras/CUPTI/lib64/libcupti.so.10.2 /usr/local/cuda/extras/CUPTI/lib64/libcupti.so.10.1