Esecuzione di carichi di lavoro di inferenza TensorFlow con TensorRT5 e GPU NVIDIA T4


Questo tutorial illustra come eseguire inferenze di deep learning su carichi di lavoro su larga scala utilizzando GPU NVIDIA TensorRT5 in esecuzione su Compute Engine.

Prima di iniziare, ecco alcuni elementi essenziali:

  • L'inferenza di deep learning è la fase del processo di machine learning in cui un modello addestrato viene utilizzato per riconoscere, elaborare e classificare i risultati.
  • NVIDIA TensorRT è una piattaforma ottimizzata per l'esecuzione di carichi di lavoro di deep learning.
  • Le GPU vengono utilizzate per accelerare i carichi di lavoro che richiedono un uso intensivo dei dati, come il machine learning e l'elaborazione di dati. Su Compute Engine è disponibile una vasta gamma di GPU NVIDIA. Questo tutorial utilizza GPU T4, poiché le GPU T4 sono progettate specificamente per carichi di lavoro di inferenza di deep learning.

Obiettivi

In questo tutorial vengono illustrate le seguenti procedure:

  • Preparazione di un modello mediante un grafico preaddestrato.
  • Test della velocità di inferenza per un modello con diverse modalità di ottimizzazione.
  • Conversione di un modello personalizzato in TensorRT in corso.
  • Configurazione di un cluster multizona. Questo cluster multizona è configurato come segue:
    • Basato su Deep Learning VM Images. Su queste immagini sono preinstallati TensorFlow, TensorFlow serve di gestione e TensorRT5.
    • Scalabilità automatica abilitata. La scalabilità automatica in questo tutorial si basa sull'utilizzo della GPU.
    • Bilanciamento del carico abilitato.
    • Firewall abilitato.
  • Esecuzione di un carico di lavoro di inferenza nel cluster multizona.

Panoramica dell'architettura di alto livello della configurazione del tutorial.

Costi

Il costo dell'esecuzione di questo tutorial varia a seconda della sezione.

Puoi calcolare il costo con il Calcolatore prezzi.

Per stimare il costo della preparazione del modello e testare le velocità di inferenza a diverse velocità di ottimizzazione, utilizza le seguenti specifiche:

  • 1 istanza VM: n1-standard-8 (vCPU: 8, RAM 30 GB)
  • 1 GPU NVIDIA T4

Per stimare il costo della configurazione del cluster multizona, utilizza le seguenti specifiche:

  • 2 istanze VM: n1-standard-16 (vCPU: 16, RAM 60 GB)
  • 4 GPU NVIDIA T4 per ogni istanza VM
  • SSD da 100 GB per ogni istanza VM
  • 1 regola di forwarding

Prima di iniziare

Configurazione del progetto

  1. Accedi al tuo account Google Cloud. Se non conosci Google Cloud, crea un account per valutare le prestazioni dei nostri prodotti in scenari reali. I nuovi clienti ricevono anche 300 $di crediti gratuiti per l'esecuzione, il test e il deployment dei carichi di lavoro.
  2. Nella pagina del selettore di progetti della console Google Cloud, seleziona o crea un progetto Google Cloud.

    Vai al selettore progetti

  3. Assicurati che la fatturazione sia attivata per il tuo progetto Google Cloud.

  4. Abilita le API Compute Engine and Cloud Machine Learning .

    Abilita le API

  5. Nella pagina del selettore di progetti della console Google Cloud, seleziona o crea un progetto Google Cloud.

    Vai al selettore progetti

  6. Assicurati che la fatturazione sia attivata per il tuo progetto Google Cloud.

  7. Abilita le API Compute Engine and Cloud Machine Learning .

    Abilita le API

Configurazione degli strumenti

Per utilizzare Google Cloud CLI in questo tutorial:

  1. Installa o aggiorna alla versione più recente di Google Cloud CLI.
  2. (Facoltativo) Imposta una regione e una zona predefinite.

Preparazione del modello

Questa sezione illustra la creazione di un'istanza di macchina virtuale (VM) utilizzata per eseguire il modello. Questa sezione spiega anche come scaricare un modello dal catalogo dei modelli ufficiali di TensorFlow.

  1. Creare l'istanza VM. Questo tutorial viene creato utilizzando tf-ent-2-10-cu113. Per le versioni più recenti dell'immagine, consulta la sezione Scelta di un sistema operativo nella documentazione di Deep Learning VM Images.

    export IMAGE_FAMILY="tf-ent-2-10-cu113"
    export ZONE="us-central1-b"
    export INSTANCE_NAME="model-prep"
    gcloud compute instances create $INSTANCE_NAME \
       --zone=$ZONE \
       --image-family=$IMAGE_FAMILY \
       --machine-type=n1-standard-8 \
       --image-project=deeplearning-platform-release \
       --maintenance-policy=TERMINATE \
       --accelerator="type=nvidia-tesla-t4,count=1" \
       --metadata="install-nvidia-driver=True"
    
  2. Seleziona un modello. Questo tutorial utilizza il modello ResNet. Questo modello ResNet viene addestrato sul set di dati ImageNet in TensorFlow.

    Per scaricare il modello ResNet nell'istanza VM, esegui questo comando:

    wget -q http://download.tensorflow.org/models/official/resnetv2_imagenet_frozen_graph.pb

    Salva la posizione del tuo modello ResNet nella variabile $WORKDIR. Sostituisci MODEL_LOCATION con la directory di lavoro che contiene il modello scaricato.

    export WORKDIR=MODEL_LOCATION

Esecuzione del test della velocità di inferenza

Questa sezione illustra le seguenti procedure:

  • Configurazione del modello ResNet.
  • Esecuzione di test di inferenza con diverse modalità di ottimizzazione.
  • Esaminare i risultati dei test di inferenza.

Panoramica della procedura di test

TensorRT può migliorare la velocità delle prestazioni per i carichi di lavoro di inferenza, ma il miglioramento più significativo deriva dal processo di quantizzazione.

La quantizzazione del modello è il processo mediante il quale riduci la precisione delle ponderazioni di un modello. Ad esempio, se la ponderazione iniziale di un modello è FP32, puoi ridurre la precisione a FP16, INT8 o persino INT4. È importante scegliere il giusto compromesso tra velocità (precisione delle ponderazioni) e precisione di un modello. Fortunatamente, TensorFlow include funzionalità che fanno esattamente questo, misura l'accuratezza rispetto alla velocità o altre metriche come velocità effettiva, latenza, tassi di conversione dei nodi e tempo totale di addestramento.

Procedura

  1. Configurare il modello ResNet. Per configurare il modello, esegui questi comandi:

    git clone https://github.com/tensorflow/models.git
    cd models
    git checkout f0e10716160cd048618ccdd4b6e18336223a172f
    touch research/__init__.py
    touch research/tensorrt/__init__.py
    cp research/tensorrt/labellist.json .
    cp research/tensorrt/image.jpg ..
    
  2. Esegui il test. Il completamento di questo comando richiede un po' di tempo.

    python -m research.tensorrt.tensorrt \
       --frozen_graph=$WORKDIR/resnetv2_imagenet_frozen_graph.pb \
       --image_file=$WORKDIR/image.jpg \
       --native --fp32 --fp16 --int8 \
       --output_dir=$WORKDIR
    

    Dove:

    • $WORKDIR è la directory in cui hai scaricato il modello ResNet.
    • Gli argomenti --native rappresentano le diverse modalità di quantizzazione da testare.
  3. Esamina i risultati. Al termine del test, puoi fare un confronto dei risultati di inferenza per ogni modalità di ottimizzazione.

    Predictions:
    Precision:  native [u'seashore, coast, seacoast, sea-coast', u'promontory, headland, head, foreland', u'breakwater, groin, groyne, mole, bulwark, seawall, jetty',     u'lakeside, lakeshore', u'grey whale, gray whale, devilfish, Eschrichtius gibbosus, Eschrichtius robustus']
    Precision:  FP32 [u'seashore, coast, seacoast, sea-coast', u'promontory, headland, head, foreland', u'breakwater, groin, groyne, mole, bulwark, seawall, jetty', u'lakeside,   lakeshore', u'sandbar, sand bar']
    Precision:  FP16 [u'seashore, coast, seacoast, sea-coast', u'promontory, headland, head, foreland', u'breakwater, groin, groyne, mole, bulwark, seawall, jetty', u'lakeside,   lakeshore', u'sandbar, sand bar']
    Precision:  INT8 [u'seashore, coast, seacoast, sea-coast', u'promontory, headland, head, foreland', u'breakwater, groin, groyne, mole, bulwark, seawall, jetty', u'grey         whale, gray whale, devilfish, Eschrichtius gibbosus, Eschrichtius robustus', u'lakeside, lakeshore']
    

    Per vedere i risultati completi, esegui questo comando:

    cat $WORKDIR/log.txt

    Risultati delle prestazioni.

    Dai risultati è possibile vedere che FP32 e FP16 sono identiche. Ciò significa che se hai familiarità con TensorRT, puoi iniziare a utilizzare subito FP16. INT8, mostra risultati leggermente peggiori.

    Inoltre, l'esecuzione del modello con TensorRT5 mostra i seguenti risultati:

    • Utilizzando l'ottimizzazione FP32, migliora la velocità effettiva del 40%, da 314 a 440 f/s. Allo stesso tempo, la latenza diminuisce di circa il 30%, rendendola di 0,28 ms anziché 0,40 ms.
    • Utilizzando l'ottimizzazione FP16, anziché il grafico TensorFlow nativo, la velocità aumenta del 214% da 314 a 988 f/s. Allo stesso tempo, la latenza si riduce di 0,12 ms, quasi 3 volte.
    • Con INT8, puoi osservare un aumento della velocità del 385% da 314 f/s a 1524 f/s, con la latenza che scende a 0,08 ms.

Conversione di un modello personalizzato in TensorRT

Per questa conversione, puoi utilizzare un modello INT8.

  1. Scarica il modello. Per convertire un modello personalizzato in un grafico TensorRT, è necessario un modello salvato. Per recuperare un modello ResNet INT8 salvato, esegui questo comando:

    wget http://download.tensorflow.org/models/official/20181001_resnet/savedmodels/resnet_v2_fp32_savedmodel_NCHW.tar.gz
    tar -xzvf resnet_v2_fp32_savedmodel_NCHW.tar.gz
  2. Converti il modello nel grafico TensorRT utilizzando TFTools. Per convertire il modello utilizzando TFTools, esegui questo comando:

    git clone https://github.com/GoogleCloudPlatform/ml-on-gcp.git
    cd ml-on-gcp/dlvm/tools
    python ./convert_to_rt.py \
       --input_model_dir=$WORKDIR/resnet_v2_fp32_savedmodel_NCHW/1538687196 \
       --output_model_dir=$WORKDIR/resnet_v2_int8_NCHW/00001 \
       --batch_size=128 \
       --precision_mode="INT8"
    

    Ora è presente un modello INT8 nella directory $WORKDIR/resnet_v2_int8_NCHW/00001.

    Per assicurarti che tutto sia configurato correttamente, prova a eseguire un test di inferenza.

    tensorflow_model_server --model_base_path=$WORKDIR/resnet_v2_int8_NCHW/ --rest_api_port=8888
  3. Caricare il modello in Cloud Storage. Questo passaggio è necessario in modo che il modello possa essere utilizzato dal cluster a più zone configurato nella sezione successiva. Per caricare il modello, completa i seguenti passaggi:

    1. Archivia il modello.

      tar -zcvf model.tar.gz ./resnet_v2_int8_NCHW/
    2. Carica l'archivio. Sostituisci GCS_PATH con il percorso del bucket Cloud Storage.

      export GCS_PATH=GCS_PATH
      gsutil cp model.tar.gz $GCS_PATH
      

      Se necessario, puoi ottenere un grafico bloccato INT8 da Cloud Storage a questo URL:

      gs://cloud-samples-data/dlvm/t4/model.tar.gz

Configurazione di un cluster a più zone

Crea il cluster

Ora che disponi di un modello sulla piattaforma Cloud Storage, puoi creare un cluster.

  1. Creare un modello di istanza. Un modello di istanza è una risorsa utile per creare nuove istanze. Vedi Modelli di istanza. Sostituisci YOUR_PROJECT_NAME con l'ID progetto.

    export INSTANCE_TEMPLATE_NAME="tf-inference-template"
    export IMAGE_FAMILY="tf-ent-2-10-cu113"
    export PROJECT_NAME=YOUR_PROJECT_NAME
    
    gcloud beta compute --project=$PROJECT_NAME instance-templates create $INSTANCE_TEMPLATE_NAME \
         --machine-type=n1-standard-16 \
         --maintenance-policy=TERMINATE \
         --accelerator=type=nvidia-tesla-t4,count=4 \
         --min-cpu-platform=Intel\ Skylake \
         --tags=http-server,https-server \
         --image-family=$IMAGE_FAMILY \
         --image-project=deeplearning-platform-release \
         --boot-disk-size=100GB \
         --boot-disk-type=pd-ssd \
         --boot-disk-device-name=$INSTANCE_TEMPLATE_NAME \
         --metadata startup-script-url=gs://cloud-samples-data/dlvm/t4/start_agent_and_inf_server_4.sh
    
    • Questo modello di istanza include uno script di avvio specificato dal parametro metadata.
      • Esegui questo script di avvio durante la creazione dell'istanza su ogni istanza che utilizza questo modello.
      • Questo script di avvio esegue i seguenti passaggi:
        • Installa un agente Monitoring che monitora l'utilizzo della GPU nell'istanza.
        • Scarica il modello.
        • Avvia il servizio di inferenza.
      • Nello script di avvio, tf_serve.py contiene la logica di inferenza. Questo esempio include un file Python molto piccolo basato sul pacchetto TFServe.
      • Per visualizzare lo script di avvio, consulta startup_inf_script.sh.
  2. Crea un gruppo di istanze gestite. Questo gruppo di istanze gestite è necessario per configurare più istanze in esecuzione in zone specifiche. Le istanze vengono create in base al modello di istanza generato nel passaggio precedente.

    export INSTANCE_GROUP_NAME="deeplearning-instance-group"
    export INSTANCE_TEMPLATE_NAME="tf-inference-template"
    gcloud compute instance-groups managed create $INSTANCE_GROUP_NAME \
       --template $INSTANCE_TEMPLATE_NAME \
       --base-instance-name deeplearning-instances \
       --size 2 \
       --zones us-central1-a,us-central1-b
    
    • Puoi creare questa istanza in qualsiasi zona disponibile che supporta le GPU T4. Assicurati di disporre di quote GPU disponibili nella zona.
    • La creazione dell'istanza richiede del tempo. Puoi controllare l'avanzamento eseguendo questi comandi:

      export INSTANCE_GROUP_NAME="deeplearning-instance-group"
      gcloud compute instance-groups managed list-instances $INSTANCE_GROUP_NAME --region us-central1

      Creazione dell'istanza.

    • Quando viene creato il gruppo di istanze gestite, dovresti vedere un output simile al seguente:

      L'istanza in esecuzione.

  3. Verifica che le metriche siano disponibili nella pagina di Google Cloud Cloud Monitoring.

    1. Nella console Google Cloud, vai alla pagina Monitoring.

      Vai a Monitoring

    2. Se nel riquadro di navigazione viene visualizzato Metrics Explorer, fai clic su Metrics Explorer. In caso contrario, seleziona Risorse e poi Metrics Explorer.

    3. Cerca gpu_utilization.

      Avvio del monitoraggio.

    4. Se arrivano dati, dovresti vedere qualcosa di simile a questo:

      Monitoraggio in esecuzione.

Abilita scalabilità automatica

  1. Abilita la scalabilità automatica per il gruppo di istanze gestite.

    export INSTANCE_GROUP_NAME="deeplearning-instance-group"
    
    gcloud compute instance-groups managed set-autoscaling $INSTANCE_GROUP_NAME \
       --custom-metric-utilization metric=custom.googleapis.com/gpu_utilization,utilization-target-type=GAUGE,utilization-target=85 \
       --max-num-replicas 4 \
       --cool-down-period 360 \
       --region us-central1
    

    custom.googleapis.com/gpu_utilization è il percorso completo della metrica. L'esempio specifica il livello 85, il che significa che ogni volta che l'utilizzo della GPU raggiunge l'85, la piattaforma crea una nuova istanza nel nostro gruppo.

  2. Testa la scalabilità automatica. Per testare la scalabilità automatica, devi eseguire questi passaggi:

    1. SSH all'istanza. Vedi Connessione alle istanze.
    2. Usa lo strumento gpu-burn per caricare la GPU al 100% di utilizzo per 600 secondi:

      git clone https://github.com/GoogleCloudPlatform/ml-on-gcp.git
      cd ml-on-gcp/third_party/gpu-burn
      git checkout c0b072aa09c360c17a065368294159a6cef59ddf
      make
      ./gpu_burn 600 > /dev/null &
      
    3. Visualizza la pagina di Cloud Monitoring. Osserva la scalabilità automatica. Il cluster fa lo scale up aggiungendo un'altra istanza.

      Scalabilità automatica nel cluster.

    4. Nella console Google Cloud, vai alla pagina Gruppi di istanze.

      Vai a Gruppi di istanze

    5. Fai clic sul gruppo di istanze gestite deeplearning-instance-group.

    6. Fai clic sulla scheda Monitoring.

      A questo punto, la logica di scalabilità automatica dovrebbe tentare di ruotare il maggior numero possibile di istanze per ridurre il carico, senza ottenere risultati:

      Istanze aggiuntive.

      A questo punto, puoi interrompere la masterizzazione delle istanze e osservare come il sistema esegue lo scale down.

Configura un bilanciatore del carico

Rivediamo le informazioni che hai ottenuto finora:

  • Un modello addestrato, ottimizzato con TensorRT5 (INT8)
  • Un gruppo di istanze gestite. Per queste istanze è abilitata la scalabilità automatica in base all'utilizzo della GPU

Ora puoi creare un bilanciatore del carico davanti alle istanze.

  1. Crea controlli di integrità. I controlli di integrità consentono di determinare se un determinato host sul nostro backend può gestire il traffico.

    export HEALTH_CHECK_NAME="http-basic-check"
    
    gcloud compute health-checks create http $HEALTH_CHECK_NAME \
       --request-path /v1/models/default \
       --port 8888
    
  2. Crea un servizio di backend che includa un gruppo di istanze e il controllo di integrità.

    1. Crea il controllo di integrità.

      export HEALTH_CHECK_NAME="http-basic-check"
      export WEB_BACKED_SERVICE_NAME="tensorflow-backend"
      
      gcloud compute backend-services create $WEB_BACKED_SERVICE_NAME \
         --protocol HTTP \
         --health-checks $HEALTH_CHECK_NAME \
         --global
      
    2. Aggiungi il gruppo di istanze al nuovo servizio di backend.

      export INSTANCE_GROUP_NAME="deeplearning-instance-group"
      export WEB_BACKED_SERVICE_NAME="tensorflow-backend"
      
      gcloud compute backend-services add-backend $WEB_BACKED_SERVICE_NAME \
         --balancing-mode UTILIZATION \
         --max-utilization 0.8 \
         --capacity-scaler 1 \
         --instance-group $INSTANCE_GROUP_NAME \
         --instance-group-region us-central1 \
         --global
      
  3. Configura l'URL di inoltro. Il bilanciatore del carico deve sapere quale URL può essere inoltrato ai servizi di backend.

    export WEB_BACKED_SERVICE_NAME="tensorflow-backend"
    export WEB_MAP_NAME="map-all"
    
    gcloud compute url-maps create $WEB_MAP_NAME \
       --default-service $WEB_BACKED_SERVICE_NAME
    
  4. Crea il bilanciatore del carico.

    export WEB_MAP_NAME="map-all"
    export LB_NAME="tf-lb"
    
    gcloud compute target-http-proxies create $LB_NAME \
       --url-map $WEB_MAP_NAME
    
  5. Aggiungi un indirizzo IP esterno al bilanciatore del carico.

    export IP4_NAME="lb-ip4"
    
    gcloud compute addresses create $IP4_NAME \
       --ip-version=IPV4 \
       --network-tier=PREMIUM \
       --global
    
  6. Trova l'indirizzo IP allocato.

    gcloud compute addresses list
  7. Configura la regola di forwarding che indica a Google Cloud di inoltrare tutte le richieste dall'indirizzo IP pubblico al bilanciatore del carico.

    export IP=$(gcloud compute addresses list | grep ${IP4_NAME} | awk '{print $2}')
    export LB_NAME="tf-lb"
    export FORWARDING_RULE="lb-fwd-rule"
    
    gcloud compute forwarding-rules create $FORWARDING_RULE \
       --address $IP \
       --global \
       --load-balancing-scheme=EXTERNAL \
       --network-tier=PREMIUM \
       --target-http-proxy $LB_NAME \
       --ports 80
    

    Dopo aver creato le regole di forwarding globali, la propagazione della configurazione può richiedere diversi minuti.

Abilita firewall

  1. Verifica se sono presenti regole firewall che consentono le connessioni da origini esterne alle tue istanze VM.

    gcloud compute firewall-rules list
  2. Se non hai regole firewall che consentono queste connessioni, devi crearle. Per creare regole firewall, esegui questi comandi:

    gcloud compute firewall-rules create www-firewall-80 \
       --target-tags http-server --allow tcp:80
    
    gcloud compute firewall-rules create www-firewall-8888 \
       --target-tags http-server --allow tcp:8888
    

Esecuzione di un'inferenza

  1. Puoi utilizzare il seguente script Python per convertire le immagini in un formato caricabile sul server.

    from PIL import Image
    import numpy as np
    import json
    import codecs
    
    img = Image.open("image.jpg").resize((240, 240)) img_array=np.array(img) result = { "instances":[img_array.tolist()] } file_path="/tmp/out.json" print(json.dump(result, codecs.open(file_path, 'w', encoding='utf-8'), separators=(',', ':'), sort_keys=True, indent=4))
  2. Eseguire l'inferenza.

    curl -X POST $IP/v1/models/default:predict -d @/tmp/out.json

Esegui la pulizia

Per evitare che al tuo Account Google Cloud vengano addebitati costi relativi alle risorse utilizzate in questo tutorial, elimina il progetto che contiene le risorse oppure mantieni il progetto ed elimina le singole risorse.

  1. Eliminare le regole di forwarding.

    gcloud compute forwarding-rules delete $FORWARDING_RULE --global
  2. Elimina l'indirizzo IPV4.

    gcloud compute addresses delete $IP4_NAME --global
  3. Elimina il bilanciatore del carico.

    gcloud compute target-http-proxies delete $LB_NAME
  4. Elimina l'URL di inoltro.

    gcloud compute url-maps delete $WEB_MAP_NAME
  5. Elimina il servizio di backend.

    gcloud compute backend-services delete $WEB_BACKED_SERVICE_NAME --global
  6. Elimina i controlli di integrità.

    gcloud compute health-checks delete $HEALTH_CHECK_NAME
  7. Elimina il gruppo di istanze gestite.

    gcloud compute instance-groups managed delete $INSTANCE_GROUP_NAME --region us-central1
  8. Elimina il modello di istanza.

    gcloud beta compute --project=$PROJECT_NAME instance-templates delete $INSTANCE_TEMPLATE_NAME
  9. Elimina le regole firewall.

    gcloud compute firewall-rules delete www-firewall-80
    gcloud compute firewall-rules delete www-firewall-8888