Messen und Optimieren der Leistung eines TensorFlow-Inferenzsystems mit Triton-Inferenzserver und Tesla T4 messen

In dieser Anleitung wird beschrieben, wie Sie die Leistung des TensorFlow-Systems messen, das Sie in Teil 2 dieser Reihe erstellt haben, und wie Sie den Systemdurchsatz mit der Parameterabstimmung verbessern. In dieser Anleitung werden nicht die Leistungsdaten eines bestimmten Systems bereitgestellt. Stattdessen erhalten Sie allgemeine Hinweise zum Vorgang der Leistungsmessung.

Die konkreten Leistungsmesswerten wie "Anfragen insgesamt pro Sekunde (RPS)" und "Antwortzeit" hängt vom trainierten Modell, der Softwareversionen und der Hardwarekonfigurationen ab.

Ziele

  • Definieren Sie das Leistungsziel und die -Messwerte.
  • Referenzleistung messen
  • Optimieren Sie die Grafik.
  • FP16-Umwandlung messen
  • INT8-Quantisierung messen
  • Anzahl der Instanzen anpassen

Kosten

Zusätzlich zur Verwendung der NVIDIA T4-GPU werden in dieser Anleitung die folgenden kostenpflichtigen Komponenten von Google Cloud verwendet:

Nach Abschluss dieser Anleitung können Sie weitere Kosten vermeiden, indem Sie die erstellten Ressourcen löschen. Weitere Informationen finden Sie unter Bereinigen.

Hinweis

Bevor Sie mit dieser Anleitung beginnen, müssen Sie das Inferenzsystem fertig erstellt haben, wie in Teil 2 dieser Reihe beschrieben. Für diese Anleitung verwenden Sie die folgenden Schnittstellen:

Legen Sie im SSH-Terminal das aktuelle Verzeichnis auf das Unterverzeichnis client fest:

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

In dieser Anleitung führen Sie alle Befehle von diesem Verzeichnis her aus.

Leistungsziel definieren

Beim Messen der Leistung von Inferenzsystemen müssen Sie das Leistungsziel und entsprechende Leistungsmesswerte gemäß dem Anwendungsfall des Systems definieren. Der Einfachheit halber werden in dieser Anleitung die folgenden Leistungsziele verwendet:

  • 95 % der Anfragen erhalten Antworten innerhalb von 100 ms.
  • Der Gesamtdurchsatz (Anfragen pro Sekunde) wird verbessert, ohne das vorherige Ziel zu beeinträchtigen.

In Erwägung dieser Ziele messen Sie den Durchsatz der folgenden ResNet-50-Modelle mit verschiedenen Optimierungen. Wenn ein Client Inferenzanfragen sendet, gibt er das Modell anhand des Modellnamens in dieser Tabelle an. Sie wenden außerdem die Parameter-Feinabstimmung an, um den Durchsatz des Modells zu verbessern.

Modellname Optimierung
original Ursprüngliches Modell (keine Optimierung mit TF-TRT)
tftrt_fp32 Grafikoptimierung
(Batchgröße: 64, Instanzgruppen: 1)
tftrt_fp16 Konvertierung in FP16 zusätzlich zur Grafikoptimierung
(Batchgröße: 64, Instanzgruppen: 1)
tftrt_int8 Quantisierung mit INT8 zusätzlich zur Grafikoptimierung
(Batchgröße: 64, Instanzgruppen: 1)
tftrt_int8_bs16_count4 Quantisierung mit INT8 zusätzlich zur Grafikoptimierung
(Batchgröße: 16, Instanzgruppen: 4)

Referenzleistung messen

Sie verwenden zuerst TF-TRT als Referenz, um die Leistung des ursprünglichen, nicht optimierten Modells zu messen. Vergleichen Sie die Leistung anderer Modelle mit dem Original, um die Leistungsverbesserung quantitativ zu bewerten. Bei der Bereitstellung von Locust wurde es bereits so konfiguriert, dass Anfragen für das ursprüngliche Modell gesendet werden.

  1. Öffnen Sie die Locust-Konsole und bestätigen Sie, dass die Anzahl der Clients (als Slaves bezeichnet) zehn ist. Wenn die Zahl unter zehn liegt, werden die Clients noch gestartet. Warten Sie in diesem Fall einige Minuten, bis sie zehn wird.
  2. Setzen Sie Anzahl der zu simulierenden Nutzer auf 3000 und setzen Sie die Hatch rate auf 5.
  3. Erhöhen Sie die Anzahl der simulierten Nutzer um 5 pro Sekunde, bis sie 3.000 erreicht, indem Sie auf Swarm starten klicken.

    Eine neue Locust-Swarm wird gestartet.

  4. Klicken Sie auf Diagramme, um die folgenden Diagramme aufzurufen.

    Eine neue Locust-Swarm wird gestartet.

    Beachten Sie, dass der Wert für die Anfragen pro Sekunde insgesamt linear erhöht wird, während der Wert Antwortzeiten (ms) entsprechend ansteigt.

  5. Wenn der Wert 95% Perzentil der Antwortzeiten 100 ms überschreitet, klicken Sie auf Stop, um die Simulation zu beenden. Wenn Sie den Mauszeiger über das Diagramm bewegen, können Sie die Anzahl der Anfragen pro Sekunde überprüfen korrespondierend zu als der Wert von 95% Perzentil der Antwortzeiten 100 ms überschritt.

    Im folgenden Screenshot beträgt die Anzahl der Anfragen pro Sekunde 253,1.

    Grafik mit 253,1 Anfragen pro Sekunde

    Wir empfehlen, diese Messung mehrmals zu wiederholen und dabei einen Durchschnittswert zu ermitteln, der Schwankungen berücksichtigt.

  6. Starten Sie Locust neu:

    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. Gehen Sie zurück zu Schritt 1, um diese Messung zu wiederholen.

Grafiken optimieren

In diesem Abschnitt messen Sie die Leistung des Modells tftrt_fp32, das mithilfe von TF-TRT für die Grafikoptimierung optimiert wird. Dies ist eine gängige Optimierung, die mit den meisten NVIDIA-GPU-Karten kompatibel ist.

  1. Starten Sie das Lasttesttool neu. Verwenden Sie die Ressource configmap, um das Modell als tftrt_fp32 anzugeben.

    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
    
  2. Starten Sie den Triton-Server neu:

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

    Warten Sie einige Minuten, bis die Serverprozesse bereit sind.

  3. Wiederholen Sie die Leistungsmessung, die Sie im vorherigen Abschnitt vorgenommen haben.

    In den folgenden Screenshots beträgt die Anzahl der Anfragen pro Sekunde 381.

    Grafik mit der Antwortzeit, wobei Anfragen pro Sekunde ist 381.

    Grafik mit 381 Anfragen pro Sekunde

    Diese Bilder zeigen die Leistungssteigerung der TF-TRT-Grafikoptimierung.

In FP16 umgewandeln

In diesem Abschnitt messen Sie die Leistung des Modells tftrt_fp16, das mit TF-TRT für die Grafikoptimierung und FP16-Konvertierung optimiert ist. Diese Optimierung ist für NVIDIA Tesla T4 verfügbar.

  1. Starten Sie das Lasttesttool neu. Verwenden Sie die Ressource configmap, um das Modell als tftrt_fp16 anzugeben.

    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. Starten Sie den Triton-Server neu:

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

    Warten Sie einige Minuten, bis die Serverprozesse bereit sind.

  3. Wiederholen Sie die Leistungsmessung, die Sie im vorherigen Abschnitt vorgenommen haben. Im folgenden Beispiel beträgt die Anzahl der Anfragen pro Sekunde 1072,5.

    Grafik mit der Antwortzeit mit 1072,5 Anfragen pro Sekunde

    Grafik mit 1072,5 Anfragen pro Sekunde

    Diese Bilder zeigen neben der Leistungsverbesserung der FP16-Konvertierung auch die TF-TRT-Grafikoptimierung.

Mit INT8 quantisieren

In diesem Abschnitt messen Sie die Leistung des Modells tftrt_int8, das mit TF-TRT für die Diagrammoptimierung und INT8-Quantisierung optimiert ist. Diese Optimierung ist für NVIDIA Tesla T4 verfügbar.

  1. Starten Sie das Lasttesttool neu. Verwenden Sie die Ressource configmap, um das Modell als tftrt_int8 anzugeben.

    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. Starten Sie den Triton-Server neu:

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

    Warten Sie einige Minuten, bis die Serverprozesse bereit sind.

  3. Wiederholen Sie die Leistungsmessung, die Sie im vorherigen Abschnitt vorgenommen haben.

    In den folgenden Screenshots beträgt die Anzahl der Anfragen pro Sekunde 1085,4.

    Grafik mit Antwortzeit mit 1085,4 Anfragen pro Sekunde.

    Diagramm mit 1085,4 Anfragen pro Sekunde.

    Dieses Ergebnis ist fast identisch mit der FP16-Conversion. Sie beobachten keinen Vorteil der INT8-Quantisierung. Theoretisch kann die NVIDIA Tesla T4-GPU schneller INT8-Quantisierungsmodelle verarbeiten als FP16-Konvertierungsmodelle. In diesem Fall kann es einen anderen Engpass als die GPU-Leistung geben. Sie können dies anhand der folgenden GPU-Auslastungsdaten im Grafana-Dashboard prüfen. Beachten Sie, dass die Auslastung unter 40 % liegt. Das bedeutet, dass das Modell die GPU-Leistung nicht vollständig nutzen kann.

    Grafik mit GPU-Auslastung von weniger als 40 %

    Wie im nächsten Abschnitt gezeigt, können Sie diesen Engpass möglicherweise beheben, indem Sie die Anzahl der Instanzgruppen erhöhen. Sie können beispielsweise die Anzahl der Instanzgruppen von 1 auf 4 erhöhen und die Batchgröße von 64 auf 16 verringern. Bei diesem Ansatz wird die Gesamtzahl der Anfragen, die auf einer einzelnen GPU verarbeitet werden, bei 64 gehalten.

Anzahl der Instanzen anpassen

In diesem Abschnitt messen Sie die Leistung des Modells tftrt_int8_bs16_count4. Dieses Modell hat die gleiche Struktur wie tftrt_int8, Sie ändern jedoch die Batchgröße und die Anzahl der Instanzgruppen wie am Ende des vorherigen Abschnitts beschrieben.

  1. Starten Sie Locust neu. Verwenden Sie die Ressource configmap, um das Modell als tftrt_int8_bs16_count4 anzugeben. Erhöhen Sie gleichzeitig die Anzahl der Locust-Client-Pods, um genügend Arbeitslasten zu generieren, um die Leistungsbeschränkung des Modells zu messen.

    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
    
  2. Starten Sie den Triton-Server neu:

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

    Warten Sie einige Minuten, bis die Serverprozesse bereit sind.

  3. Wiederholen Sie die Leistungsmessung, die Sie im vorherigen Abschnitt vorgenommen haben. Setzen Sie in diesem Fall aber die Trefferquote auf 15, da das Erreichen der Leistungsgrenze sehr lange dauert, wenn Sie die Hatch-Rate auf 5 gesetzt haben. Im folgenden Beispiel beträgt die Anzahl der Anfragen pro Sekunde 2236,6.

    Grafik mit der Antwortzeit mit 2236,6 Anfragen pro Sekunde.

    Grafik mit 2236,6 Anfragen pro Sekunde.

    Wenn Sie die Anzahl der Instanzen anpassen, verdoppeln Sie die Zahl der Anfragen pro Sekunde fast. Die GPU-Auslastung hat im Dashboard von Grafana etwa 75% erreicht.

    Grafik mit GPU-Auslastung von 75 %

Mit mehreren Knoten skalieren

Bei der Skalierung mit mehreren Knoten messen Sie die Leistung eines einzelnen Pods. Da die Inferenzprozesse unabhängig voneinander auf verschiedenen Pods nach dem Prinzip shared-nothing ausgeführt werden, können Sie davon ausgehen, dass der Gesamtdurchsatz linear mit der Anzahl der Pods skaliert wird. Diese Annahme gilt, solange keine Engpässe wie die Netzwerkbandbreite zwischen Clients und Inferenzservern vorliegen.

Sie müssen jedoch verstehen, wie Inferenzanfragen auf mehrere Inferenzserver verteilt werden. Triton verwendet das gRPC-Protokoll, um eine TCP-Verbindung zwischen einem Client und einem Server herzustellen. Da Triton die hergestellte Verbindung zum Senden mehrerer Inferenzanfragen wiederverwendet, werden Anfragen von einem einzelnen Client immer an denselben Server gesendet. Sie müssen mehrere Clients verwenden, um Anfragen für mehrere Server zu verteilen.

Bereinigen

Projekt löschen

  1. Wechseln Sie in der Cloud Console zur Seite Ressourcen verwalten.

    Zur Seite „Ressourcen verwalten“

  2. Wählen Sie in der Projektliste das Projekt aus, das Sie löschen möchten, und klicken Sie dann auf Löschen.
  3. Geben Sie im Dialogfeld die Projekt-ID ein und klicken Sie auf Shut down (Beenden), um das Projekt zu löschen.

Nächste Schritte