Questo documento descrive come eseguire il deployment dell'architettura di riferimento descritta in Sistema di inferenza TensorFlow scalabile.
Questa serie è rivolta agli sviluppatori che conoscono Google Kubernetes Engine e machine learning (ML), tra cui TensorFlow e NVIDIA TensorRT.
Una volta completato il deployment, Misura e ottimizza le prestazioni di un sistema di inferenza TensorFlow.
Architettura
Il seguente diagramma mostra l'architettura del sistema di inferenza.
Cloud Load Balancing invia il traffico delle richieste al cluster GKE più vicino. Il cluster contiene un pod per ogni nodo. In ogni pod, viene inserito un Triton Inference Server fornisce un servizio di inferenza (per la pubblicazione di modelli ResNet-50) e un server La GPU migliora le prestazioni. I server di monitoraggio nel cluster raccolgono i dati delle metriche sull'utilizzo della GPU e sulla memoria.
Per maggiori dettagli, consulta Sistema di inferenza TensorFlow scalabile.
Obiettivi
- Scarica un modello ResNet-50 e utilizzare l'integrazione TensorFlow con TensorRT (TF-TRT) per applica ottimizzazioni
- Pubblicare un modello ResNet-50 da un server di inferenza NVIDIA Triton
- Crea un sistema di monitoraggio per Triton utilizzando Prometheus e Grafana
- Crea uno strumento di test di carico utilizzando Locust
Costi
Oltre alla GPU NVIDIA T4, in questo deployment utilizzerai i seguenti di Google Cloud:
Per generare una stima dei costi in base all'utilizzo previsto, utilizza il calcolatore prezzi.
Al termine del deployment, non eliminare le risorse che hai creato, Ti servono queste risorse quando misuri e ottimizzi il deployment.
Prima di iniziare
- Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the GKE API.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the GKE API.
Crea modelli ottimizzati con TF-TRT
In questa sezione, creerai un ambiente di lavoro e ottimizzerai il modello preaddestrato.
Il modello preaddestrato utilizza il set di dati falso all'indirizzo gs://cloud-tpu-test-datasets/fake_imagenet/
.
È inoltre disponibile una copia del modello preaddestrato nella località di Cloud Storage all'indirizzo gs://solutions-public-assets/tftrt-tutorial/resnet/export/1584366419/
.
Creare un ambiente di lavoro
Per il tuo ambiente di lavoro, puoi creare un'istanza Compute Engine utilizzando Deep Learning VM Image. Ottimizzi e quantizzi il modello ResNet-50 con TensorRT su questa istanza.
In the Google Cloud console, activate Cloud Shell.
Esegui il deployment di un'istanza denominata
working-vm
:gcloud config set project PROJECT_ID gcloud config set compute/zone us-west1-b gcloud compute instances create working-vm \ --scopes cloud-platform \ --image-family common-cu113 \ --image-project deeplearning-platform-release \ --machine-type n1-standard-8 \ --min-cpu-platform="Intel Skylake" \ --accelerator=type=nvidia-tesla-t4,count=1 \ --boot-disk-size=200GB \ --maintenance-policy=TERMINATE \ --metadata="install-nvidia-driver=True"
Sostituisci
PROJECT_ID
con l'ID del progetto Google Cloud che hai creato in precedenza.Questo comando avvia un'istanza Compute Engine utilizzando NVIDIA T4. Al primo avvio, viene installato automaticamente il driver GPU NVIDIA compatibile con TensorRT 5.1.5.
Creare file del modello con ottimizzazioni diverse
In questa sezione, applicherai le seguenti ottimizzazioni al modello ResNet-50 originale utilizzando TF-TRT:
- Ottimizzazione del grafico
- Conversione a FP16 con l'ottimizzazione del grafico
- Quantizzazione con INT8 con l'ottimizzazione del grafo
Per maggiori dettagli su queste ottimizzazioni, consulta Ottimizzazione del rendimento.
Nella console Google Cloud, vai a Compute Engine > Istanze VM.
Viene visualizzata l'istanza
working-vm
che hai creato in precedenza.Per aprire la console del terminale dell'istanza, fai clic su SSH.
Potrai utilizzare questo terminale per eseguire il resto dei comandi in questo documento.
Nel terminale, clona il repository richiesto e modifica la directory attuale:
cd $HOME git clone https://github.com/GoogleCloudPlatform/gke-tensorflow-inference-system-tutorial cd gke-tensorflow-inference-system-tutorial/server
Scarica il modello ResNet-50 preaddestrato in una directory locale:
mkdir -p models/resnet/original/00001 gcloud storage cp gs://solutions-public-assets/tftrt-tutorial/resnet/export/1584366419/* models/resnet/original/00001 --recursive
Crea un'immagine container che contenga strumenti di ottimizzazione per TF-TRT:
docker build ./ -t trt-optimizer docker image list
L'ultimo comando mostra una tabella di repository.
Nella tabella, nella riga del repository
tft-optimizer
, copia l'ID immagine.Applica le ottimizzazioni (ottimizzazione del grafico, conversione in FP16 e quantizzazione) con INT8) al modello originale:
export IMAGE_ID=IMAGE_ID nvidia-docker run --rm \ -v `pwd`/models/:/workspace/models ${IMAGE_ID} \ --input-model-dir='models/resnet/original/00001' \ --output-dir='models/resnet' \ --precision-mode='FP32' \ --batch-size=64 nvidia-docker run --rm \ -v `pwd`/models/:/workspace/models ${IMAGE_ID} \ --input-model-dir='models/resnet/original/00001' \ --output-dir='models/resnet' \ --precision-mode='FP16' \ --batch-size=64 nvidia-docker run --rm \ -v `pwd`/models/:/workspace/models ${IMAGE_ID} \ --input-model-dir='models/resnet/original/00001' \ --output-dir='models/resnet' \ --precision-mode='INT8' \ --batch-size=64 \ --calib-image-dir='gs://cloud-tpu-test-datasets/fake_imagenet/' \ --calibration-epochs=10
Sostituisci
IMAGE_ID
con l'ID immagine pertft-optimizer
che hai copiato in passaggio precedente.L'opzione
--calib-image-dir
specifica la posizione dei dati di addestramento viene usato per il modello preaddestrato. Gli stessi dati di addestramento vengono usati per una per la quantizzazione di INT8. Il processo di calibrazione può richiedere circa 5 minuti.Al termine dell'esecuzione dei comandi, l'ultima riga di output è simile alla seguente, in cui i modelli ottimizzati vengono salvati in
./models/resnet
:INFO:tensorflow:SavedModel written to: models/resnet/INT8/00001/saved_model.pb
La struttura della directory è simile alla seguente:
models └── resnet ├── FP16 │ └── 00001 │ ├── saved_model.pb │ └── variables ├── FP32 │ └── 00001 │ ├── saved_model.pb │ └── variables ├── INT8 │ └── 00001 │ ├── saved_model.pb │ └── variables └── original └── 00001 ├── saved_model.pb └── variables ├── variables.data-00000-of-00001 └── variables.index
La tabella seguente riassume la relazione tra directory e ottimizzazioni.
Directory | Ottimizzazione |
---|---|
FP16 |
Conversione a FP16 in aggiunta all'ottimizzazione del grafico |
FP32 |
Ottimizzazione del grafico |
INT8 |
Quantizzazione con INT8 oltre all'ottimizzazione del grafico |
original |
Modello originale (nessuna ottimizzazione con TF-TRT) |
esegui il deployment di un server di inferenza
In questa sezione eseguirai il deployment dei server Triton con cinque modelli. Innanzitutto, carica in Cloud Storage il file binario del modello che hai creato nella sezione precedente. Quindi, creerai un cluster GKE il deployment dei server Triton sul cluster.
Carica il programma binario del modello
Nel terminale SSH, carica i file binari del modello e i file di configurazione
config.pbtxt
in un bucket di archiviazione:export PROJECT_ID=PROJECT_ID export BUCKET_NAME=${PROJECT_ID}-models mkdir -p original/1/model/ cp -r models/resnet/original/00001/* original/1/model/ cp original/config.pbtxt original/1/model/ cp original/imagenet1k_labels.txt original/1/model/ mkdir -p tftrt_fp32/1/model/ cp -r models/resnet/FP32/00001/* tftrt_fp32/1/model/ cp tftrt_fp32/config.pbtxt tftrt_fp32/1/model/ cp tftrt_fp32/imagenet1k_labels.txt tftrt_fp32/1/model/ mkdir -p tftrt_fp16/1/model/ cp -r models/resnet/FP16/00001/* tftrt_fp16/1/model/ cp tftrt_fp16/config.pbtxt tftrt_fp16/1/model/ cp tftrt_fp16/imagenet1k_labels.txt tftrt_fp16/1/model/ mkdir -p tftrt_int8/1/model/ cp -r models/resnet/INT8/00001/* tftrt_int8/1/model/ cp tftrt_int8/config.pbtxt tftrt_int8/1/model/ cp tftrt_int8/imagenet1k_labels.txt tftrt_int8/1/model/ mkdir -p tftrt_int8_bs16_count4/1/model/ cp -r models/resnet/INT8/00001/* tftrt_int8_bs16_count4/1/model/ cp tftrt_int8_bs16_count4/config.pbtxt tftrt_int8_bs16_count4/1/model/ cp tftrt_int8_bs16_count4/imagenet1k_labels.txt tftrt_int8_bs16_count4/1/model/ gcloud storage buckets create gs://${BUCKET_NAME} gcloud storage cp original tftrt_fp32 tftrt_fp16 tftrt_int8 tftrt_int8_bs16_count4 \ gs://${BUCKET_NAME}/resnet/ --recursive
Sostituisci
PROJECT_ID
con ID del progetto Google Cloud che hai creato in precedenza.Nel file
config.pbtxt
sono specificati i seguenti parametri di ottimizzazione:- Nome modello
- Nome tensore di input e nome tensore di output
- Allocazione delle GPU per ogni modello
- Dimensione del batch e numero di gruppi di istanze
Ad esempio, il file
original/1/model/config.pbtxt
include i seguenti contenuti:name: "original" platform: "tensorflow_savedmodel" max_batch_size: 64 input { name: "input" data_type: TYPE_FP32 format: FORMAT_NHWC dims: [ 224, 224, 3 ] } output { name: "probabilities" data_type: TYPE_FP32 dims: 1000 label_filename: "imagenet1k_labels.txt" } default_model_filename: "model" instance_group [ { count: 1 kind: KIND_GPU } ] dynamic_batching { preferred_batch_size: [ 64 ] max_queue_delay_microseconds: 20000 }
Per maggiori dettagli sulla dimensione del batch e sul numero di gruppi di istanze, consulta Ottimizzazione del rendimento.
La tabella seguente riassume i cinque modelli di cui hai eseguito il deployment .
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 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) |
Esegui il deployment dei server di inferenza utilizzando Triton
Nel terminale SSH, installa e configura il pacchetto di autenticazione, gestisce i cluster GKE:
export USE_GKE_GCLOUD_AUTH_PLUGIN=True sudo apt-get install google-cloud-sdk-gke-gcloud-auth-plugin
Crea un cluster GKE e un pool di nodi GPU con nodi di computing che utilizzano una GPU NVIDIA T4:
gcloud auth login gcloud config set compute/zone us-west1-b gcloud container clusters create tensorrt-cluster \ --num-nodes=20 gcloud container node-pools create t4-gpu-pool \ --num-nodes=1 \ --machine-type=n1-standard-8 \ --cluster=tensorrt-cluster \ --accelerator type=nvidia-tesla-t4,count=1
Il flag
--num-nodes
specifica 20 istanze per l'istruzione GKE e un'istanza per il pool di nodi GPUt4-gpu-pool
.Il pool di nodi GPU è costituito di una singola istanza
n1-standard-8
con una GPU NVIDIA T4. Il numero di Le istanze GPU devono essere uguali o maggiori del numero del server di inferenza poiché la GPU NVIDIA T4 non può essere condivisa da più pod nella stessa istanza.Mostra le informazioni sul cluster:
gcloud container clusters list
L'output è simile al seguente:
NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS tensorrt-cluster us-west1-b 1.14.10-gke.17 XX.XX.XX.XX n1-standard-1 1.14.10-gke.17 21 RUNNING
Mostra le informazioni sul pool di nodi:
gcloud container node-pools list --cluster tensorrt-cluster
L'output è simile al seguente:
NAME MACHINE_TYPE DISK_SIZE_GB NODE_VERSION default-pool n1-standard-1 100 1.14.10-gke.17 t4-pool n1-standard-8 100 1.14.10-gke.17
Abilita il carico di lavoro
daemonSet
:gcloud container clusters get-credentials tensorrt-cluster kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/master/nvidia-driver-installer/cos/daemonset-preloaded.yaml
Questo comando carica il driver GPU NVIDIA sui nodi nel nodo GPU. piscina. Inoltre, carica automaticamente il driver quando aggiungi un nuovo nodo Pool di nodi GPU.
Esegui il deployment dei server di inferenza sul cluster:
sed -i.bak "s/YOUR-BUCKET-NAME/${PROJECT_ID}-models/" trtis_deploy.yaml kubectl create -f trtis_service.yaml kubectl create -f trtis_deploy.yaml
Attendi qualche minuto finché i servizi non diventano disponibili.
Ottieni l'indirizzo
clusterIP
di Triton e archivialo in un ambiente variabile:export TRITON_IP=$(kubectl get svc inference-server \ -o "jsonpath={.spec['clusterIP']}") echo ${TRITON_IP}
A questo punto, il server di inferenza fornisce quattro modelli ResNet-50 che si creato nella sezione Crea file di modello con ottimizzazioni diverse. I client possono specificare il modello da utilizzare quando inviano richieste di inferenza.
Esegui il deployment di server di monitoraggio con Prometheus e Grafana
Nel terminale SSH, esegui il deployment dei server Prometheus nel cluster:
sed -i.bak "s/CLUSTER-IP/${TRITON_IP}/" prometheus-configmap.yml kubectl create namespace monitoring kubectl apply -f prometheus-service.yml -n monitoring kubectl create -f clusterRole.yml kubectl create -f prometheus-configmap.yml -n monitoring kubectl create -f prometheus-deployment.yml -n monitoring
Ottieni l'URL dell'endpoint del servizio Prometheus.
ip_port=$(kubectl get svc prometheus-service \ -o "jsonpath={.spec['clusterIP']}:{.spec['ports'][0]['port']}" -n monitoring) echo "http://${ip_port}"
Prendi nota dell'URL dell'endpoint di Prometheus, perché lo utilizzerai per configurare Grafana in seguito.
Esegui il deployment dei server Grafana nel cluster:
kubectl create -f grafana-service.yml -n monitoring kubectl create -f grafana-deployment.yml -n monitoring
Attendi qualche minuto finché tutti i servizi non diventano disponibili.
Ottieni l'URL dell'endpoint del servizio Grafana.
ip_port=$(kubectl get svc grafana-service \ -o "jsonpath={.status['loadBalancer']['ingress'][0]['ip']}:{.spec['ports'][0]['port']}" -n monitoring) echo "http://${ip_port}"
Prendi nota dell'URL dell'endpoint di Grafana da utilizzare nel passaggio successivo.
In un browser web, vai all'URL Grafana che hai annotato nel passaggio precedente.
Accedi con l'ID utente e la password predefiniti (
admin
eadmin
). Quando richiesto, cambia la password predefinita.Fai clic su Aggiungi la tua prima origine dati e sulla scheda Data e ora nell'elenco dei database della serie, seleziona Prometheus.
Nella scheda Settings (Impostazioni), nel campo URL, inserisci l'endpoint Prometheus che hai annotato in precedenza.
Fai clic su Salva e testa e poi torna a la schermata Home.
Aggiungi una metrica di monitoraggio per
nv_gpu_utilization
:- Fai clic su Crea la tua prima dashboard, quindi su Aggiungi visualizzazione.
- Nell'elenco Origine dati, seleziona Prometheus.
Nella scheda Query, nel campo Metrica, inserisci
nv_gpu_utilization
.Nella sezione Opzioni del riquadro, nel campo Titolo, inserisci
GPU Utilization
e fai clic su Applica.La pagina mostra un riquadro per l'utilizzo della GPU.
Aggiungi una metrica di monitoraggio per
nv_gpu_memory_used_bytes
:- Fai clic su Aggiungi e seleziona Visualizzazione.
Nella scheda Query, inserisci
nv_gpu_memory_used_bytes
nel campo Metrica.Nella sezione Opzioni del riquadro, nel campo Titolo, inserisci
GPU Memory Used
e fai clic su Salva.
Per aggiungere la dashboard, fai clic su Salva nel riquadro Salva dashboard.
Vengono visualizzati i grafici relativi a Utilizzo GPU e Memoria GPU utilizzata.
Esegui il deployment di uno strumento di test di carico
In questa sezione, eseguirai il deployment dello strumento di test del carico Locust GKE e generare carico di lavoro per misurare le prestazioni di inferenza.
Nel terminale SSH, crea un'immagine Docker che contenga le librerie client Triton e carica in Container Registry:
cd ../client git clone https://github.com/triton-inference-server/server cd server git checkout r19.05 sed -i.bak "s/bootstrap.pypa.io\/get-pip.py/bootstrap.pypa.io\/pip\/2.7\/get-pip.py/" Dockerfile.client docker build -t tritonserver_client -f Dockerfile.client . gcloud auth configure-docker docker tag tritonserver_client \ gcr.io/${PROJECT_ID}/tritonserver_client docker push gcr.io/${PROJECT_ID}/tritonserver_client
Il processo di compilazione può richiedere circa 5 minuti. Al termine del processo, nel terminale SSH viene visualizzato un prompt dei comandi.
Al termine del processo di compilazione, crea un'immagine Docker per generare il carico di lavoro di test e caricala in Container Registry:
cd .. sed -i.bak "s/YOUR-PROJECT-ID/${PROJECT_ID}/" Dockerfile docker build -t locust_tester -f Dockerfile . docker tag locust_tester gcr.io/${PROJECT_ID}/locust_tester docker push gcr.io/${PROJECT_ID}/locust_tester
Non modificare o sostituire
YOUR-PROJECT-ID
nei comandi.Questa immagine è stata creata a partire da quella che hai creato nel passaggio precedente.
Esegui il deployment dei file Locust
service_master.yaml
edeployment_master.yaml
:sed -i.bak "s/YOUR-PROJECT-ID/${PROJECT_ID}/" deployment_master.yaml sed -i.bak "s/CLUSTER-IP-TRTIS/${TRITON_IP}/" deployment_master.yaml kubectl create namespace locust kubectl create configmap locust-config --from-literal model=original --from-literal saddr=${TRITON_IP} --from-literal rps=10 -n locust kubectl apply -f service_master.yaml -n locust kubectl apply -f deployment_master.yaml -n locust
La risorsa
configmap
viene utilizzata per specificare il modello di machine learning per quali client inviano richieste di inferenza.Attendi qualche minuto finché i servizi non diventano disponibili.
Ottieni l'indirizzo
clusterIP
del clientlocust-master
e memorizzalo in una variabile di ambiente:export LOCUST_MASTER_IP=$(kubectl get svc locust-master -n locust \ -o "jsonpath={.spec['clusterIP']}") echo ${LOCUST_MASTER_IP}
Esegui il deployment del client Locust:
sed -i.bak "s/YOUR-PROJECT-ID/${PROJECT_ID}/" deployment_slave.yaml sed -i.bak "s/CLUSTER-IP-LOCUST-MASTER/${LOCUST_MASTER_IP}/" deployment_slave.yaml kubectl apply -f deployment_slave.yaml -n locust
Questi comandi eseguono il deployment di 10 pod client Locust che puoi utilizzare per generare carichi di lavoro di test. Se non riesci a generare un numero sufficiente di richieste con di client, puoi modificare il numero di pod utilizzando seguente comando:
kubectl scale deployment/locust-slave --replicas=20 -n locust
Quando la capacità di un cluster predefinito non è sufficiente per aumentare di repliche, ti consigliamo di aumentare il numero di nodi nel cluster GKE.
Copia l'URL della console Locust e apri questo URL in un browser web:
export LOCUST_IP=$(kubectl get svc locust-master -n locust \ -o "jsonpath={.status.loadBalancer.ingress[0].ip}") echo "http://${LOCUST_IP}:8089"
Si apre la console Locust, dalla quale puoi generare carichi di lavoro di test.
Controlla i pod in esecuzione
Per assicurarti che il deployment dei componenti venga eseguito correttamente, verifica che i pod siano in esecuzione.
Nel terminale SSH, controlla il pod del server di inferenza:
kubectl get pods
L'output è simile al seguente:
NAME READY STATUS RESTARTS AGE inference-server-67786cddb4-qrw6r 1/1 Running 0 83m
Se non ottieni l'output previsto, assicurati di aver completato i passaggi descritti in Deployment dei server di inferenza utilizzando Triton.
Controlla i pod Locust:
kubectl get pods -n locust
L'output è simile al seguente:
NAME READY STATUS RESTARTS AGE locust-master-75f6f6d4bc-ttllr 1/1 Running 0 10m locust-slave-76ddb664d9-8275p 1/1 Running 0 2m36s locust-slave-76ddb664d9-f45ww 1/1 Running 0 2m36s locust-slave-76ddb664d9-q95z9 1/1 Running 0 2m36s
Se non ottieni l'output previsto, assicurati di aver completato i passaggi descritti in Deployment di uno strumento di test del carico.
Controlla i pod di monitoraggio:
kubectl get pods -n monitoring
L'output è simile al seguente:
NAME READY STATUS RESTARTS AGE grafana-deployment-644bbcb84-k6t7v 1/1 Running 0 79m prometheus-deployment-544b9b9f98-hl7q8 1/1 Running 0 81m
Se non ottieni l'output previsto, assicurati di aver completato i passaggi descritti in Eseguire il deployment dei server di monitoraggio con Prometheus e Grafana.
Nella prossima parte di questa serie, userai questo sistema server di inferenza per apprendere il modo in cui le varie ottimizzazioni migliorano il rendimento e come interpretarle ottimizzazioni. Per i passaggi successivi, vedi Misurare e ottimizzare le prestazioni di un sistema di inferenza TensorFlow.
Passaggi successivi
- Scopri di più su Google Kubernetes Engine (GKE).
- Scopri di più su Cloud Load Balancing.
- Per altre architetture di riferimento, diagrammi e best practice, esplora il Centro architetture cloud.