In dieser Anleitung erfahren Sie, wie Sie eine Inferenz mit NVIDIA TensorRT 5- und T4-GPUs in großem Umfang ausführen. NVIDIA TensorRT™ ist eine Plattform für hochleistungsfähige Deep-Learning-Inferenz. Sie beinhaltet einen Deep-Learning-Inferenzoptimierer und eine Laufzeit mit niedrigen Latenzzeiten und einem hohen Durchsatz für Deep-Learning-Inferenzanwendungen.
In dieser Anleitung richten Sie einen Mehrzonencluster für die Ausführung einer Inferenz mit einer Gruppe ein, die automatisch auf Basis der GPU-Nutzung skaliert wird.
Übersicht
In dieser Anleitung wird Folgendes bereitgestellt:
- Eine Referenzarchitektur zur Implementierung eines skalierbaren Inferenzsystems für maschinelles Lernen in Google Cloud, das für eine Entwicklungsumgebung geeignet ist. Da Infrastruktur- und Sicherheitsanforderungen variieren, können Sie die in dieser Anleitung beschriebenen Konfigurationen entsprechend anpassen.
- Ein GitHub-Repository mit Skripts, die Sie in dieser Anleitung verwenden können, um das TensorFlow-Modell und andere erforderliche Komponenten zu installieren.
- Anleitungen zum Quantisieren des TensorFlow-Modells mit TensorRT, zum Bereitstellen von Skripts und zum Bereitstellen der Referenzarchitektur.
- Anleitung zum Konfigurieren von Cloud Load Balancing
Nach Abschluss dieser Anleitung haben Sie ein vorab trainiertes, quantisiertes Modell in Cloud Storage und zwei geclusterte Instanzgruppen in Compute Engine in verschiedenen Regionen. Der Webtraffic wird über Cloud Load Balancing zu den Instanzen weitergeleitet. Diese Architektur wird im folgenden Diagramm dargestellt.
Ziele
- Sie beginnen mit einer vorab trainierten Grafik.
- Sie optimieren das Modell mit TensorRT und stellen fest, wie sich verschiedene Optimierungen auf die Geschwindigkeit des Modells auswirken.
- Sie erstellen nach Fertigstellen des Modells einen Cluster auf Basis der Deep-Learning-VM der Compute Engine, die mit bereits vorinstalliertem TensorFlow, TensorFlow Serving und TensorRT 5 bereitgestellt werden.
Kosten
In dieser Anleitung werden die folgenden kostenpflichtigen Komponenten von Google Cloud verwendet:
- Compute Engine
- Persistent Disk
- Cloud Storage
- Netzwerk
- NVIDIA T4-GPU
Mit dem Preisrechner können Sie eine Kostenschätzung für Ihre voraussichtliche Nutzung vornehmen. Neuen Google Cloud-Nutzern steht möglicherweise eine kostenlose Testversion zur Verfügung.
Hinweis
-
Rufen Sie in der Google Cloud Console die Seite für die Projektauswahl auf.
-
Wählen Sie ein Google Cloud-Projekt aus oder erstellen Sie eines.
-
Die Abrechnung für das Cloud-Projekt muss aktiviert sein. So prüfen Sie, ob die Abrechnung für Ihr Projekt aktiviert ist.
- Compute Engine and Cloud Logging APIs aktivieren.
- Achten Sie auf ein ausreichendes GPU-Kontingent zum Erstellen von VMs.
Nach Abschluss dieser Anleitung können Sie weitere Kosten vermeiden, indem Sie die erstellten Ressourcen löschen. Weitere Informationen finden Sie unter Bereinigen.
Umgebung vorbereiten
In diesem Abschnitt legen Sie Standardeinstellungen für Werte fest, die in der gesamten Anleitung verwendet werden, zum Beispiel Region und Zone. In dieser Anleitung verwenden Sie us-central1
als Standardregion und us-central1-b
als Standardzone.
Außerdem erstellen Sie eine Datei mit allen Einstellungen. Damit können die Variablen automatisch geladen werden, falls Sie Cloud Shell noch einmal öffnen und die Einstellungen neu initialisieren müssen.
Öffnen Sie Cloud Shell:
Legen Sie die Standardregion und -zone fest.
gcloud compute project-info add-metadata \ --metadata google-compute-default-region=us-central1,google-compute-default-zone=us-central1-a
Initialisieren Sie die Shell neu:
gcloud init --console-only
Drücken Sie bei den ersten drei Fragen
1
und geben Sie dann bei der letzten Frage die Projekt-ID ein.
Modell mit TensorRT optimieren
Erstellen Sie in Cloud Shell eine Instanz für die Modellvorbereitung:
export IMAGE_FAMILY="tf-latest-cu100" export INSTANCE_NAME="model-prep" gcloud compute instances create $INSTANCE_NAME \ --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"
Eine GPU ist mehr als ausreichend, damit Sie verschiedene TensorRT-Optimierungsmodi vergleichen und ein Gefühl dafür bekommen können, wie schnell eine einzelne GPU sein kann.
Nachdem die VM-Instanz erstellt wurde, stellen Sie mit
ssh
eine Verbindung zur VM her.Laden Sie in der Instanz das Modell
resnetv2
aus dem offiziellen TensorFlow-Repository herunter, damit Sie die TensorRT-Optimierung testen können:wget -q http://download.tensorflow.org/models/official/resnetv2_imagenet_frozen_graph.pb
TensorRT kann die Inferenz beschleunigen, zusätzliche Verbesserungen werden jedoch durch Quantisierung erreicht. Die lineare Modellquantisierung konvertiert Gewichtungen und Aktivierungen von Gleitkomma- zu Ganzzahlen. Wenn die anfängliche Gewichtung des Modells beispielsweise FP32 ist (32-Bit-Gleitkommazahl), können Sie durch Verringerung der Genauigkeit INT8 verwenden. Die Quantisierung hat jedoch Auswirkungen: Durch die Reduzierung der Speicherdarstellung können Sie die Genauigkeit des Modells minimal reduzieren. Der Übergang von FP32 zu FP16 bleibt jedoch praktisch ohne negative Auswirkungen.
Wie finden Sie den richtigen Kompromiss zwischen Geschwindigkeit (Genauigkeit der Gewichtungen) und Genauigkeit des Modells? Es gibt dafür bereits vorhandenen Code. Dieser Code kann die Genauigkeit im Verhältnis zur Geschwindigkeit und zu anderen Messwerten messen. Der Test ist auf Bilderkennungsmodelle beschränkt. Es ist jedoch nicht schwierig, einen auf diesem Code basierenden benutzerdefinierten Test zu implementieren.
Laden Sie in Cloud Shell einen benutzerdefinierten Test herunter und implementieren Sie ihn:
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 .
Bereiten Sie den Test für die Ausführung vor:
python -m research.tensorrt.tensorrt \ --frozen_graph=$HOME/resnetv2_imagenet_frozen_graph.pb \ --image_file=$HOME/models/image.jpg \ --native --fp32 --fp16 --int8 \ --output_dir=$HOME
Der Test erfordert eine fixierte Grafik (das zuvor heruntergeladene Modell resnetv2) und Argumente für die verschiedenen zu testenden Quantisierungsmodi. Der Abschluss dieses Befehls dauert einige Zeit.
Wenn die Ausführung abgeschlossen ist, zeigt die daraus resultierende Ausgabe einen Vergleich der Inferenzergebnisse der verschiedenen Versionen der Grafik:
Die Ergebnisse von FP32 und FP16 sind identisch und zeigen die gleiche Genauigkeit. Wenn Sie also mit TensorRT arbeiten möchten, können Sie auf jeden Fall sofort mit FP16 beginnen. Im Gegensatz dazu zeigt INT8 etwas weniger genaue Ergebnisse.
Lassen Sie die Werte für die Genauigkeit anzeigen:
cat $HOME/log.txt
Dieser Befehl erzeugt folgende Ausgabe:
TensorRT 5 zeigt die folgenden Ergebnisse, alle im Vergleich mit "native":
- Bei FP32 verbesserte sich der Durchsatz um ca. 34 % von 319,1 fps auf 428,2 fps.
- Bei FP16 verbesserte sich der Durchsatz um ca. 207 % von 319,1 fps auf 979,6 fps.
- Bei INT8 verbesserte sich der Durchsatz um ca. 376 % von 319,1 fps auf 1519,5 fps.
Folgendes können Sie aus diesen Ergebnissen lernen:
- Der Übergang von nativ zu TensorRT wirkt sich auf die Unsicherheit aus. Wenn Sie jedoch mit den geringen Auswirkungen einverstanden sind, können Sie wahrscheinlich direkt zu FP16 wechseln.
- INT8 ist zwar sehr schnell, aber die Auswirkungen sind merklich ausgeprägter.
Im nächsten Abschnitt wird das INT8-Modell verwendet.
Benutzerdefiniertes Modell nach TensorRT konvertieren
Zum Konvertieren eines Modells in einen TensorRT-Graphen benötigen Sie ein SavedModel.
Laden Sie in Cloud Shell das folgende vorab trainierte SavedModel herunter:
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
Erstellen Sie ein Python-Skript, das das fixierte Modell in eine TensorRT-Grafik konvertiert:
cat <<EOF > convert_to_rt.py import tensorflow.contrib.tensorrt as trt import argparse parser = argparse.ArgumentParser(description="Converts TF SavedModel to the TensorRT enabled graph.") parser.add_argument("--input_model_dir", required=True) parser.add_argument("--output_model_dir", required=True) parser.add_argument("--batch_size", type=int, required=True) parser.add_argument("--precision_mode", choices=["FP32", "FP16", "INT8"], required=True) args = parser.parse_args() trt.create_inference_graph( None, None, max_batch_size=args.batch_size, input_saved_model_dir=args.input_model_dir, output_saved_model_dir=args.output_model_dir, precision_mode=args.precision_mode) EOF
Konvertieren Sie das Modell in die TensorRT-Grafik:
python ./convert_to_rt.py \ --input_model_dir=$HOME/resnet_v2_fp32_savedmodel_NCHW/1538687196 \ --output_model_dir=$HOME/resnet_v2_int8_NCHW/00001 \ --batch_size=128 \ --precision_mode="INT8"
Sie haben nun ein INT8-Modell im Ordner
$HOME/resnet_v2_int8_NCHW/00001
.Führen Sie eine Inferenz aus, um zu prüfen, ob alles funktioniert:
tensorflow_model_server --model_base_path=$HOME/resnet_v2_int8_NCHW/ --rest_api_port=8888
Senden Sie die folgende Beispieleingabe, um zu prüfen, ob es funktioniert:
curl -X POST localhost:8888/v1/models/default:predict -d '{"instances": [[[[1,1,1]]]]}'
Wenn Sie Ergebnisse von diesem
curl
-Befehl sehen, beenden Sie die ausgeführte Inferenz durch Drücken von Strg+C.Damit Sie das optimierte Modell in Ihrem Cluster verwenden können, laden Sie das Modell in Cloud Storage hoch und ersetzen Sie
[GCS_PATH]
durch den Namen des Cloud Storage-Buckets:tar -zcvf model.tar.gz ./resnet_v2_int8_NCHW/ export GCS_PATH=[GCS_PATH] gsutil cp model.tar.gz $GCS_PATH
Wenn Sie dieses Modell das nächste Mal verwenden möchten, müssen Sie nicht diesen gesamten Vorgang wiederholen. Stattdessen können Sie die fixierte INT8-Grafik im Cloud Storage-Bucket verwenden:
gs://solutions-public-assets/tensorrt-t4-gpu/model.tar.gz
Cluster einrichten
Da Sie jetzt ein Modell in Cloud Storage haben, können Sie einen Cluster erstellen. Als Erstes erstellen Sie dazu eine VM-Vorlage. Der Cluster verwendet die VM-Vorlage zum Erstellen neuer Instanzen.
Laden Sie in Cloud Shell den zum Einrichten des Clusters benötigten Code herunter:
git clone https://github.com/GoogleCloudPlatform/tensorflow-inference-tensorrt5-t4-gpu.git
Erstellen Sie die VM-Vorlage und ersetzen Sie
[PROJECT_NAME]
durch Ihren Projektnamen:export PROJECT_NAME=[PROJECT_NAME] export INSTANCE_TEMPLATE_NAME="tf-inference-template" export IMAGE_FAMILY="tf-latest-cu100" 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://solutions-public-assets/tensorrt-t4-gpu/start_agent_and_inf_server.sh
Mit dem Parameter
metadata
wird ein Startskript angegeben, das in jeder durch die VM-Vorlage erstellten Instanz installiert ist. Das Startskript führt die folgenden Aufgaben aus, wenn die VM-Instanz gestartet wird:- NVIDIA-Treiber installieren
- Monitoring-Agent zur Überwachung der GPU-Nutzung installieren
- Modell herunterladen
- Inferenzdienst starten
Wenn die Vorlage fertig ist, können Sie die verwaltete Instanzgruppe erstellen. Die Gruppe ist keine Skalierungsgruppe und es werden keine Systemdiagnosen durchgeführt. Sie erstellen eine Gruppe mit nur der einen Garantie, dass zwei Instanzen in bestimmten Zonen ausgeführt werden.
Erstellen Sie die verwaltete Instanzgruppe:
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
Der Wert
INSTANCE_TEMPLATE_NAME
ist der Name der Instanz, den Sie in einem vorherigen Schritt festgelegt haben. Wählen Sie Zonen anhand der Verfügbarkeit von GPUs (nicht alle GPUs sind in allen Zonen verfügbar) und Ihrer Kontingente aus.Das Erstellen der Gruppe dauert einige Zeit.
Überwachen Sie den Fortschritt mit dem folgenden Befehl:
gcloud compute instance-groups managed list-instances $INSTANCE_GROUP_NAME --region us-central1
Die Ausgabe sieht in etwa so aus:
Wenn die Erstellung abgeschlossen ist, erhalten Sie in etwa folgende Ausgabe:
Öffnen Sie in der Cloud Console die Seite "Monitoring".
Achten Sie darauf, dass Sie sich im richtigen Projektarbeitsbereich befinden. Dieser wird in der oberen linken Ecke angezeigt. Wenn Sie diese Seite zum ersten Mal besuchen, müssen Sie einen neuen Arbeitsbereich erstellen.
Wählen Sie auf der Seite Metrics Explorer für Ressourcentyp
GCE VM Instance
und für Messwertcustom/gpu_utilization
aus:Wenn Daten eingehen, sehen Sie in etwa Folgendes:
Aktivieren Sie in Cloud Shell das Autoscaling für Ihre Gruppe:
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
Der wichtige Teil hier ist der Pfad für die Auslastung:
custom.googleapis.com/gpu_utilization
. Dies ist der vollständige Pfad zum Messwert. Da Sie eine Zielauslastung von 85 angegeben haben, wird immer eine neue Instanz in der Gruppe erstellt, wenn die GPU-Auslastung 85 % erreicht.
Autoscaling testen
Führen Sie folgende Schritte aus, um das im vorherigen Abschnitt eingerichtete Autoscaling zu testen:
- Stellen Sie mit SSH eine Verbindung zu einer der Deep-Learning-GPU-Instanzen her.
- Belasten Sie alle GPUs zu 100 %.
- Beobachten Sie, wie sich die Autoscaling-Gruppe durch das Erstellen einer weiteren Instanz vergrößert.
- Stellen Sie über
ssh
eine Verbindung zur Instanz her. Lasten Sie die GPU 600 Sekunden lang zu 100 % aus:
git clone https://github.com/GoogleCloudPlatform/tensorflow-inference-tensorrt5-t4-gpu.git cd tensorflow-inference-tensorrt5-t4-gpu git submodule update --init --recursive cd third_party/gpu-burn make ./gpu_burn 600 > /dev/null &
Achten Sie in der Cloud Console auf die Aktivität auf der Seite Metrics Explorer:
Erstellen Sie die zweite Instanz.
Wechseln Sie zur Seite Google Compute Engine > Instanzgruppen > Monitoring und beobachten Sie die Aktivität:
An diesem Punkt versucht das Autoscaling erfolglos, so viele Instanzen wie möglich einzurichten, um die Last zu reduzieren. Folgendes passiert:
Beenden Sie das Starten von Instanzen und beobachten Sie, wie die Aktivität abnimmt.
Folgendes haben Sie nun eingerichtet:
- Ein trainiertes Modell, optimiert mit TensorRT 5 (INT8)
- Eine verwaltete Gruppe von Deep-Learning-Instanzen
- Autoscaling basierend auf der GPU-Nutzung
Load-Balancer erstellen
Der letzte Schritt ist das Erstellen eines Load-Balancers vor den Instanzen.
Erstellen Sie in Cloud Shell Systemdiagnosen, damit Sie feststellen können, ob ein bestimmter Host im Back-End den Traffic verarbeiten kann:
gcloud compute health-checks create http $HEALTH_CHECK_NAME \ --request-path /v1/models/default \ --port 8888
Konfigurieren Sie die benannten Ports der Instanzgruppe, damit der Load-Balancer Inferenzanfragen über Port 80 an den über Port 8888 bereitgestellten Inferenzdienst weiterleiten kann:
gcloud compute instance-groups set-named-ports $INSTANCE_GROUP_NAME \ --named-ports http:8888 \ --region us-central1
Erstellen Sie einen Back-End-Dienst.
export WEB_BACKED_SERVICE_NAME="tensorflow-backend" gcloud compute backend-services create $WEB_BACKED_SERVICE_NAME \ --protocol HTTP \ --health-checks $HEALTH_CHECK_NAME \ --global
Ein Back-End-Dienst ist eine Instanzgruppe mit Systemdiagnose.
Fügen Sie die Instanzgruppe dem neuen Back-End-Dienst hinzu:
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
Teilen Sie dem Load-Balancer mit, welche URL an den Back-End-Dienst weitergeleitet werden soll:
export WEB_MAP_NAME="map-all" gcloud compute url-maps create $WEB_MAP_NAME \ --default-service $WEB_BACKED_SERVICE_NAME
Erstellen Sie den Load-Balancer:
export LB_NAME="tf-lb" gcloud compute target-http-proxies create $LB_NAME \ --url-map $WEB_MAP_NAME
Erstellen Sie eine externe IP-Adresse für den Load-Balancer:
export IP4_NAME="lb-ip4" gcloud compute addresses create $IP4_NAME \ --ip-version=IPV4 \ --global
Prüfen Sie, ob die IP-Adresse zugewiesen wurde:
gcloud compute addresses list
Prüfen Sie die Weiterleitungsregel, die Google Cloud verwendet, um alle Anfragen von der öffentlichen IP-Adresse an den Load-Balancer weiterzuleiten.
export IP=$(gcloud compute addresses list | grep ${IP4_NAME} | awk '{print $2}') export FORWARDING_RULE="lb-fwd-rule" gcloud compute forwarding-rules create $FORWARDING_RULE \ --address $IP \ --global \ --target-http-proxy $LB_NAME \ --ports 80
Nachdem Sie die globalen Weiterleitungsregeln erstellt haben, kann es mehrere Minuten dauern, bis die Konfiguration verfügbar ist.
Damit Sie eine Verbindung zu externen Instanzen herstellen können, aktivieren Sie die Firewall im Projekt:
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
Konvertieren Sie das Bild in ein Format, das an den Server gesendet werden kann:
cat <<EOF > load_and_convert_image.py 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)) EOF
Führen Sie eine Inferenz aus:
wget https://pixnio.com/free-images/2017/10/31/2017-10-31-10-43-58-1032x825.jpg -O image.jpg python load_and_convert_image.py curl -X POST $IP/v1/models/default:predict -d @/tmp/out.json
Wenn die Inferenz richtig funktioniert, sieht das Ergebnis in etwa so aus:
Bereinigen
Nachdem Sie diese Anleitung abgeschlossen haben, können Sie die in Google Cloud erstellten Ressourcen bereinigen, damit sie keine kostenpflichtigen Kontingente verbrauchen. In den folgenden Abschnitten erfahren Sie, wie Sie diese Ressourcen löschen oder deaktivieren.
- Wechseln Sie in der Cloud Console zur Seite Ressourcen verwalten.
- Wählen Sie in der Projektliste das Projekt aus, das Sie löschen möchten, und klicken Sie dann auf Löschen.
- Geben Sie im Dialogfeld die Projekt-ID ein und klicken Sie auf Shut down (Beenden), um das Projekt zu löschen.