Misura e ottimizza le prestazioni di un sistema di inferenza TensorFlow

Last reviewed 2023-11-02 UTC

Questo documento descrive come misurare le prestazioni del sistema di inferenza TensorFlow creato in Deployment di un sistema di inferenza TensorFlow scalabile. Illustra inoltre come applicare l'ottimizzazione dei parametri per migliorare la velocità effettiva del sistema.

Il deployment si basa sull'architettura di riferimento descritta in Sistema di inferenza TensorFlow scalabile.

Questa serie è rivolta agli sviluppatori che hanno già familiarità con Google Kubernetes Engine e con i framework di machine learning (ML), tra cui TensorFlow e TensorRT.

Questo documento non ha lo scopo di fornire i dati sulle prestazioni di un determinato sistema. Offre invece indicazioni generali sul processo di misurazione del rendimento. Le metriche sulle prestazioni visualizzate, ad esempio Richieste totali al secondo (RPS) e Tempi di risposta (ms), variano a seconda del modello addestrato, delle versioni software e delle configurazioni hardware utilizzate.

Architettura

Per una panoramica dell'architettura del sistema di inferenza TensorFlow, vedi Sistema di inferenza TensorFlow scalabile.

Obiettivi

  • Definire l'obiettivo di rendimento e le metriche
  • Misura il rendimento di riferimento
  • Esegui ottimizzazione del grafico
  • Misura conversione FP16
  • Misura la quantizzazione INT8
  • Modifica il numero di istanze

Costi

Per maggiori dettagli sui costi associati al deployment, consulta Costi.

Una volta completate le attività descritte in questo documento, puoi evitare la fatturazione continua eliminando le risorse che hai creato. Per ulteriori informazioni, consulta la pagina Pulizia.

Prima di iniziare

Assicurati di aver già completato i passaggi descritti in Eseguire il deployment di un sistema di inferenza TensorFlow scalabile.

In questo documento vengono utilizzati i seguenti strumenti:

Imposta la directory

  1. Nella console Google Cloud, vai a Compute Engine > Istanze VM.

    Vai a Istanze VM

    Vedrai l'istanza working-vm che hai creato.

  2. Per aprire la console terminale dell'istanza, fai clic su SSH.

  3. Nel terminale SSH, imposta la directory corrente sulla sottodirectory client:

    cd $HOME/gke-tensorflow-inference-system-tutorial/client
    

    In questo documento eseguirai tutti i comandi da questa directory.

Definire l'obiettivo di rendimento

Quando misuri le prestazioni dei sistemi di inferenza, devi definire l'obiettivo di prestazioni e le metriche di prestazioni appropriate in base al caso d'uso del sistema. A scopo dimostrativo, questo documento utilizza i seguenti obiettivi di rendimento:

  • Almeno il 95% delle richieste riceve risposte entro 100 ms.
  • La velocità effettiva totale, rappresentata dalle richieste al secondo (RPS), migliora senza interrompere l'obiettivo precedente.

Utilizzando queste ipotesi, puoi misurare e migliorare la velocità effettiva dei seguenti modelli ResNet-50 con ottimizzazioni diverse. Quando un client invia richieste di inferenza, specifica il modello utilizzando il nome del modello in questa tabella.

Nome modello Ottimizzazione
original Modello originale (nessuna ottimizzazione con TF-TRT)
tftrt_fp32 Ottimizzazione del grafico
(dimensione batch: 64, gruppi di istanze: 1)
tftrt_fp16 Conversione a FP16 oltre all'ottimizzazione del grafico
(dimensione batch: 64, gruppi di istanze: 1)
tftrt_int8 Quantizzazione con INT8 oltre all'ottimizzazione del grafico
(dimensione del batch: 64, gruppi di istanze: 1)
tftrt_int8_bs16_count4 Quantizzazione con INT8 oltre all'ottimizzazione del grafico
(dimensione batch: 16, gruppi di istanze: 4)

Misura il rendimento di riferimento

Per iniziare, puoi utilizzare TF-TRT come riferimento per misurare le prestazioni del modello originale non ottimizzato. Puoi confrontare le prestazioni di altri modelli con l'originale per valutare quantitativamente il miglioramento. Quando hai eseguito il deployment di Locust, questo era già configurato per inviare richieste per il modello originale.

  1. Apri la console Locust che hai preparato in Eseguire il deployment di uno strumento di test di carico.

  2. Conferma che il numero di client (chiamati slave) sia pari a 10.

    Se il numero è inferiore a 10, i client sono ancora in fase di avvio. In questo caso, attendi qualche minuto finché non diventa 10.

  3. Misura il rendimento:

    1. Nel campo Numero di utenti da simulare, inserisci 3000.
    2. Nel campo Frequenza di schiusa, inserisci 5.
    3. Per aumentare il numero di utilizzi simulati di 5 al secondo fino a raggiungere 3000, fai clic su Avvia sciame.

  4. Fai clic su Grafici.

    I grafici mostrano i risultati del rendimento. Tieni presente che, mentre il valore Richieste totali al secondo aumenta in modo lineare, il valore Tempi di risposta (ms) aumenta di conseguenza.

    Avvio un nuovo sciame di locuste.

  5. Quando il valore del 95% dei tempi di risposta supera i 100 ms, fai clic su Interrompi per interrompere la simulazione.

    Se tieni il puntatore sul grafico, puoi controllare il numero di richieste al secondo corrispondente a quando il valore del Percentile 95% dei tempi di risposta ha superato 100 ms.

    Ad esempio, nello screenshot seguente il numero di richieste al secondo è 253, 1.

    Grafico che mostra 253,1 richieste al secondo.

    Ti consigliamo di ripetere la misurazione più volte e di prendere una media per tenere conto delle fluttuazioni.

  6. Nel terminale SSH, riavvia Locust:

    kubectl delete -f deployment_master.yaml -n locust
    kubectl delete -f deployment_slave.yaml -n locust
    kubectl apply -f deployment_master.yaml -n locust
    kubectl apply -f deployment_slave.yaml -n locust
    
  7. Per ripetere la misurazione, ripeti questa procedura.

Ottimizza i grafici

In questa sezione misuri le prestazioni del modello tftrt_fp32, ottimizzato con TF-TRT per l'ottimizzazione dei grafici. Si tratta di un'ottimizzazione comune compatibile con la maggior parte delle schede GPU NVIDIA.

  1. Nel terminale SSH, riavvia lo strumento di test del carico:

    kubectl delete configmap locust-config -n locust
    kubectl create configmap locust-config \
        --from-literal model=tftrt_fp32 \
        --from-literal saddr=${TRITON_IP} \
        --from-literal rps=10 -n locust
    kubectl delete -f deployment_master.yaml -n locust
    kubectl delete -f deployment_slave.yaml -n locust
    kubectl apply -f deployment_master.yaml -n locust
    kubectl apply -f deployment_slave.yaml -n locust
    

    La risorsa configmap specifica il modello come tftrt_fp32.

  2. Riavvia il server Triton:

    kubectl scale deployment/inference-server --replicas=0
    kubectl scale deployment/inference-server --replicas=1
    

    Attendi qualche minuto finché i processi del server non sono pronti.

  3. Controlla lo stato del server:

    kubectl get pods
    

    L'output è simile al seguente, in cui la colonna READY mostra lo stato del server:

    NAME                                READY   STATUS    RESTARTS   AGE
    inference-server-74b85c8c84-r5xhm   1/1     Running   0          46s
    

    Il valore 1/1 nella colonna READY indica che il server è pronto.

  4. Misura il rendimento:

    1. Nel campo Numero di utenti da simulare, inserisci 3000.
    2. Nel campo Frequenza di schiusa, inserisci 5.
    3. Per aumentare il numero di utilizzi simulati di 5 al secondo fino a raggiungere 3000, fai clic su Avvia sciame.

    I grafici mostrano il miglioramento delle prestazioni dell'ottimizzazione del grafico TF-TRT.

    Ad esempio, il grafico potrebbe mostrare che ora il numero di richieste al secondo è pari a 381 con un tempo di risposta medio di 59 ms.

Converti in FP16

In questa sezione misuri le prestazioni del modello tftrt_fp16, ottimizzato con TF-TRT per l'ottimizzazione del grafico e la conversione FP16. Questa è un'ottimizzazione disponibile per NVIDIA T4.

  1. Nel terminale SSH, riavvia lo strumento di test del carico:

    kubectl delete configmap locust-config -n locust
    kubectl create configmap locust-config \
        --from-literal model=tftrt_fp16 \
        --from-literal saddr=${TRITON_IP} \
        --from-literal rps=10 -n locust
    kubectl delete -f deployment_master.yaml -n locust
    kubectl delete -f deployment_slave.yaml -n locust
    kubectl apply -f deployment_master.yaml -n locust
    kubectl apply -f deployment_slave.yaml -n locust
    
  2. Riavvia il server Triton:

    kubectl scale deployment/inference-server --replicas=0
    kubectl scale deployment/inference-server --replicas=1
    

    Attendi qualche minuto finché i processi del server non sono pronti.

  3. Misura il rendimento:

    1. Nel campo Numero di utenti da simulare, inserisci 3000.
    2. Nel campo Frequenza di schiusa, inserisci 5.
    3. Per aumentare il numero di utilizzi simulati di 5 al secondo fino a raggiungere 3000, fai clic su Avvia sciame.

    I grafici mostrano il miglioramento delle prestazioni della conversione FP16 in aggiunta all'ottimizzazione del grafico TF-TRT.

    Ad esempio, il grafico potrebbe mostrare che il numero di richieste al secondo è 1072,5 con un tempo di risposta medio di 63 ms.

Quantizza con INT8

In questa sezione misuri le prestazioni del modello tftrt_int8, ottimizzato con TF-TRT per l'ottimizzazione dei grafici e la quantizzazione di INT8. Questa ottimizzazione è disponibile per NVIDIA T4.

  1. Nel terminale SSH, riavvia lo strumento di test del carico.

    kubectl delete configmap locust-config -n locust
    kubectl create configmap locust-config \
        --from-literal model=tftrt_int8 \
        --from-literal saddr=${TRITON_IP} \
        --from-literal rps=10 -n locust
    kubectl delete -f deployment_master.yaml -n locust
    kubectl delete -f deployment_slave.yaml -n locust
    kubectl apply -f deployment_master.yaml -n locust
    kubectl apply -f deployment_slave.yaml -n locust
    
  2. Riavvia il server Triton:

    kubectl scale deployment/inference-server --replicas=0
    kubectl scale deployment/inference-server --replicas=1
    

    Attendi qualche minuto finché i processi del server non sono pronti.

  3. Misura il rendimento:

    1. Nel campo Numero di utenti da simulare, inserisci 3000.
    2. Nel campo Frequenza di schiusa, inserisci 5.
    3. Per aumentare il numero di utilizzi simulati di 5 al secondo fino a raggiungere 3000, fai clic su Avvia sciame.

    I grafici mostrano i risultati del rendimento.

    Ad esempio, il grafico potrebbe mostrare che il numero di richieste al secondo è 1085,4 con un tempo di risposta medio di 32 ms.

    In questo esempio, il risultato non è un aumento significativo del rendimento rispetto alla conversione FP16. In teoria, la GPU NVIDIA T4 è in grado di gestire i modelli di quantizzazione INT8 più velocemente rispetto ai modelli di conversione FP16. In questo caso, potrebbe esserci un collo di bottiglia diverso dalle prestazioni della GPU. Puoi verificarlo dai dati sull'utilizzo della GPU nella dashboard di Grafana. Ad esempio, se l'utilizzo è inferiore al 40%, significa che il modello non può utilizzare completamente le prestazioni della GPU.

    Come illustrato nella sezione successiva, potresti essere in grado di alleviare questo collo di bottiglia aumentando il numero di gruppi di istanze. Ad esempio, aumenta il numero di gruppi di istanze da 1 a 4 e riduci le dimensioni del batch da 64 a 16. Questo approccio mantiene a 64 il numero totale di richieste elaborate su una singola GPU.

Modifica il numero di istanze

In questa sezione misuri le prestazioni del modello tftrt_int8_bs16_count4. Questo modello ha la stessa struttura di tftrt_int8, ma modificherai le dimensioni del batch e il numero di gruppi di istanze come descritto in Quantificare con INT8.

  1. Nel terminale SSH, riavvia Locust:

    kubectl delete configmap locust-config -n locust
    kubectl create configmap locust-config \
        --from-literal model=tftrt_int8_bs16_count4 \
        --from-literal saddr=${TRITON_IP} \
        --from-literal rps=10 -n locust
    kubectl delete -f deployment_master.yaml -n locust
    kubectl delete -f deployment_slave.yaml -n locust
    kubectl apply -f deployment_master.yaml -n locust
    kubectl apply -f deployment_slave.yaml -n locust
    kubectl scale deployment/locust-slave --replicas=20 -n locust
    

    In questo comando, utilizzerai la risorsa configmap per specificare il modello come tftrt_int8_bs16_count4. Aumenta anche il numero di pod client Locust per generare un numero di carichi di lavoro sufficiente a misurare la limitazione delle prestazioni del modello.

  2. Riavvia il server Triton:

    kubectl scale deployment/inference-server --replicas=0
    kubectl scale deployment/inference-server --replicas=1
    

    Attendi qualche minuto finché i processi del server non sono pronti.

  3. Misura il rendimento:

    1. Nel campo Numero di utenti da simulare, inserisci 3000.
    2. Nel campo Frequenza di schiusa, inserisci 15. Per questo modello, il raggiungimento del limite di prestazioni potrebbe richiedere molto tempo se la Frequenza di HAtch è impostata su 5.
    3. Per aumentare il numero di utilizzi simulati di 5 al secondo fino a raggiungere 3000, fai clic su Avvia sciame.

    I grafici mostrano i risultati del rendimento.

    Ad esempio, il grafico potrebbe mostrare che il numero di richieste al secondo è 2236,6 con un tempo di risposta medio di 38 ms.

    Modificando il numero di istanze, puoi quasi raddoppiare le richieste al secondo. Nota che l'utilizzo della GPU è aumentato sulla dashboard di Grafana (ad esempio, l'utilizzo potrebbe raggiungere il 75%).

Prestazioni e più nodi

Quando scala con più nodi, misuri le prestazioni di un singolo pod. Poiché i processi di inferenza vengono eseguiti in modo indipendente su pod diversi in modalità senza condivisione, si può presumere che la velocità effettiva totale venga scalata in modo lineare con il numero di pod. Questo presupposto è valido a condizione che non ci siano colli di bottiglia, ad esempio la larghezza di banda della rete tra client e server di inferenza.

Tuttavia, è importante comprendere come le richieste di inferenza vengono bilanciate tra più server di inferenza. Triton utilizza il protocollo gRPC per stabilire una connessione TCP tra un client e un server. Poiché Triton riutilizza la connessione stabilita per l'invio di più richieste di inferenza, le richieste da un singolo client vengono sempre inviate allo stesso server. Per distribuire le richieste per più server, devi utilizzare più client.

Esegui la pulizia

Per evitare che al tuo account Google Cloud vengano addebitati costi relativi alle risorse utilizzate in questa serie, puoi eliminare il progetto.

Elimina il progetto

  1. Nella console Google Cloud, vai alla pagina Gestisci risorse.

    Vai a Gestisci risorse

  2. Nell'elenco dei progetti, seleziona il progetto che vuoi eliminare, quindi fai clic su Elimina.
  3. Nella finestra di dialogo, digita l'ID del progetto e fai clic su Chiudi per eliminare il progetto.

Passaggi successivi