Beschleunigung der Inferenz mit Sparsity mithilfe der NVIDIA Ampere Architecture und NVIDIA TensorRT

Dieser Beitrag wurde am 20. Juli 2021 aktualisiert, um NVIDIA TensorRT 8.0-Updates widerzuspiegeln.

Bei der Bereitstellung eines neuronalen Netzwerks ist es sinnvoll, darüber nachzudenken, wie das Netzwerk schneller ausgeführt werden kann oder weniger Platz beansprucht. Ein effizienteres Netzwerk kann in einem begrenzten Zeitbudget bessere Vorhersagen treffen, schneller auf unerwartete Eingaben reagieren oder in eingeschränkte Bereitstellungsumgebungen passen.

Sparsity ist eine Optimierungstechnik, die verspricht, diese Ziele zu erreichen. Wenn das Netzwerk Nullen enthält, müssen Sie sie nicht speichern oder verarbeiten. Die Vorteile der Sparsity scheinen nur einfach. Es gibt seit langem drei Herausforderungen, um die versprochenen Gewinne zu realisieren.

  • Beschleunigung– Feinkörnige, unstrukturierte, gewichtete Sparsity hat keine Struktur und kann die Vektor- und Matrixbefehle, die in effizienter Hardware verfügbar sind, nicht verwenden, um allgemeine Netzwerkoperationen zu beschleunigen. Standardmäßige Sparse-Formate sind für alle außer hohen Sparsities ineffizient.
  • Richtigkeit—Um eine sinnvolle Beschleunigung mit feinkörniger, unstrukturierter Sparsity zu erreichen, muss das Netzwerk spärlich gemacht werden, was oft zu Genauigkeitsverlusten führt. Alternative Beschneidungsmethoden, die versuchen, die Beschleunigung zu erleichtern, wie etwa grobkörniges Beschneiden, bei dem Gewichtsblöcke, Kanäle oder ganze Schichten entfernt werden, können noch früher auf Genauigkeitsprobleme stoßen. Dies begrenzt den potenziellen Leistungsvorteil.
  • Arbeitsablauf— Ein Großteil der aktuellen Forschung zum Netzwerk-Pruning dient als nützliche Existenzbeweise. Es hat sich gezeigt, dass Netzwerk A Sparsity X erreichen kann. Das Problem tritt auf, wenn Sie versuchen, Sparsity X auf Netzwerk B anzuwenden. Es funktioniert möglicherweise nicht aufgrund von Unterschieden in Netzwerk, Task, Optimierer oder anderen Hyperparametern.

In diesem Beitrag diskutieren wir, wie die NVIDIA Ampere Architecture diese Herausforderungen bewältigt. NVIDIA veröffentlicht heute TensorRT Version 8.0, die Unterstützung für die Sparse Tensor Cores bietet, die auf den NVIDIA Ampere Architecture GPUs verfügbar sind.

TensorRT ist ein SDK für hochleistungsfähige Deep-Learning-Inferenz, das einen Optimierer und eine Laufzeit umfasst, die die Latenz minimieren und den Durchsatz in der Produktion maximieren. Durch einen einfachen Trainingsworkflow und die Bereitstellung mit TensorRT 8.0 können Sparse Tensor Cores unnötige Berechnungen in neuronalen Netzwerken eliminieren, was im Vergleich zu dichten Netzwerken zu einer Leistungssteigerung von über 30 % pro Watt führt.

Sparse Tensor Cores beschleunigen 2:4 feinkörnige strukturierte Sparsity

Die NVIDIA A100 GPU unterstützt ihre Tensor-Cores mit feinkörniger strukturierter Sparsity. Sparse Tensor Cores beschleunigen ein 2:4 Sparsity-Muster. In jedem zusammenhängenden Block von vier Werten müssen zwei Werte null sein. Dies führt natürlich zu einer Knappheit von 50%, die feinkörnig ist. Es werden keine Vektor- oder Blockstrukturen zusammengeschnitten. Ein solches regelmäßiges Muster ist leicht zu komprimieren und hat einen geringen Metadaten-Overhead (Abbildung 1).

Abbildung 1. Eine 2:4-strukturierte dünn besetzte Matrix W und ihre komprimierte Darstellung

Sparse Tensor Cores beschleunigen dieses Format, indem sie nur mit Werten ungleich Null in der komprimierten Matrix arbeiten. Sie verwenden die Metadaten, die mit Nicht-Nullen gespeichert sind, um nur die erforderlichen Werte aus dem anderen, unkomprimierten Operanden zu ziehen. Bei einer zweifachen Sparsity können sie also die gleiche effektive Berechnung in der Hälfte der Zeit durchführen. Tabelle 1 zeigt Details zu der Vielzahl von Datentypen, die von Sparse Tensor Cores unterstützt werden.

Eingabeoperanden Akkumulator Dichte TOPS vs. FFMA Spare TOPS vs. FFMA
FP32 FP32 19,5
TF32 FP32 156 8X 312 16X
FP16 FP32 312 16X 624 32X
BF16 FP32 312 16X 624 32X
FP16 FP16 312 16X 624 32X
INT8 INT32 624 32X 1248 64X

Tabelle 1. Leistung von Sparse Tensor Cores in der NVIDIA Ampere Architektur.

2:4 strukturierte spärliche Netzwerke sorgen für Genauigkeit

Natürlich ist Leistung ohne gute Genauigkeit sinnlos. Wir haben einen einfachen Trainingsworkflow entwickelt, der problemlos ein 2:4-strukturiertes dünn besetztes Netzwerk generieren kann, das der Genauigkeit des dichten Netzwerks entspricht:

  1. Beginnen Sie mit einem dichten Netzwerk. Das Ziel besteht darin, mit einem bekanntermaßen guten Modell zu beginnen, dessen Gewichtungen konvergiert sind, um nützliche Ergebnisse zu liefern.
  2. Beschneiden Sie im dichten Netzwerk die Gewichtungen, um die strukturierten 2:4-Kriterien zu erfüllen. Entfernen Sie von vier Elementen nur zwei.
  3. Wiederholen Sie den ursprünglichen Trainingsvorgang.

Dieser Arbeitsablauf verwendet One-Shot-Pruning in Schritt 2. Nach der Pruning-Phase ist das Sparsity-Muster fixiert. Es gibt viele Möglichkeiten, Beschneidungsentscheidungen zu treffen. Welche Gewichte sollen bleiben und welche auf Null gezwungen werden? Wir haben festgestellt, dass eine einfache Antwort gut funktioniert: Gewichtsgröße. Wir ziehen es vor, Werte zu beschneiden, die bereits nahe Null liegen.

Wie Sie vielleicht erwarten, kann das plötzliche Drehen der Hälfte der Gewichtungen in einem Netzwerk auf Null die Genauigkeit des Netzwerks beeinträchtigen. Schritt 3 stellt diese Genauigkeit mit genügend Gewichtsaktualisierungsschritten wieder her, um die Gewichte konvergieren zu lassen, und einer ausreichend hohen Lernrate, damit sich die Gewichte ausreichend bewegen können. Dieses Rezept funktioniert unglaublich gut. Über eine Vielzahl von Netzwerken hinweg wird ein Modell mit geringer Dichte generiert, das die Genauigkeit des dichten Netzwerks aus Schritt 1 beibehält.

Tabelle 2 enthält ein Beispiel von FP16-Genauigkeitsergebnissen, die wir mit diesem in der PyTorch Library Automatic SParsity (ASP) implementierten Workflow erhalten haben. Weitere Informationen zu den vollständigen Ergebnissen für FP16 und INT8 finden Sie im Whitepaper Accelerating Sparse Deep Neural Networks.

Netzwerk Datensatz Metrisch Dichtes FP16 Sparse FP16
ResNet-50 ImageNet Top 1 76,1 76,2
ResNeXt-101_32x8d ImageNet Top 1 79,3 79,3
Xception ImageNet Top 1 79,2 79,2
SSD-RN50 COCO2017 bbAP 24.8 24.8
MaskeRCNN-RN50 COCO2017 bbAP 37,9 37,9
FairSeq-Transformator DE-DIE WMT’14 BLAU 28,2 28,5
BERT-Groß SQuAD v1.1 F1 91,9 91,9

Tabelle 2. Stichprobengenauigkeit von 2:4-strukturierten spärlichen Netzwerken, die mit unserem Rezept trainiert wurden.

Fallstudie: ResNeXt-101_32x8d

So einfach lässt sich der Workflow mit ResNeXt-101_32x8d als Ziel verwenden.

Generieren des Sparse-Modells

Sie verwenden das vortrainierte Torchvision-Modell, sodass Schritt 1 bereits erledigt ist. Da Sie ASP verwenden, besteht die erste Codeänderung darin, die Bibliothek zu importieren:

try: from apex.contrib.sparsity ASP importieren außer ImportError: raise RuntimeError(“Fehler beim Importieren von ASP. Bitte installieren Sie Apex von https://github.com/nvidia/apex.”)

Laden Sie das vortrainierte Modell für diesen Trainingslauf. Anstatt jedoch die dichten Gewichtungen zu trainieren, bereinigen Sie das Modell und bereiten den Optimierer vor der Trainingsschleife vor (Schritt 2 des Workflows):

ASP.prune_trained_model(model, Optimizer) print(“Start training”) start_time = time.time() für Epoche im Bereich(args.start_epoch, args.epochs): …

Das ist es. Die Trainingsschleife wird wie gewohnt fortgesetzt, wobei der Standardbefehl erweitert wird, um mit dem vortrainierten Modell zu beginnen, das die ursprünglichen Hyperparameter und Optimierereinstellungen für das erneute Training wiederverwendet:

python -m Torch.distributed.launch –nproc_per_node=8 –use_env train.py –model resnext101_32x8d –epochs 100 –pretrained True

Wenn das Training abgeschlossen ist (Schritt 3), sollte sich die Netzwerkgenauigkeit erholt haben, um der des vortrainierten Modells zu entsprechen, wie in Tabelle 2 gezeigt. Wie üblich stammt der Prüfpunkt mit der besten Leistung möglicherweise nicht aus der letzten Epoche.

Vorbereitung für Schlussfolgerungen

Verwenden Sie für Rückschlüsse TensorRT 8.0, um den spärlichen Prüfpunkt des trainierten Modells zu importieren. Das Modell muss vor dem Import in TensorRT vom nativen Framework-Format in das ONNX-Format konvertiert werden. Die Konvertierung kann durchgeführt werden, indem Sie den Notizbüchern im Quickstart/IntroNotebooks GitHub-Repository folgen.

Das spärliche ResNeXt-101_32x8d haben wir bereits in das ONNX-Format konvertiert. Sie können dieses Modell von NGC herunterladen. Wenn Sie NGC nicht installiert haben, verwenden Sie den folgenden Befehl, um NGC zu installieren:

cd /usr/local/bin && wget https://ngc.nvidia.com/downloads/ngccli_cat_linux.zip && ngccli_cat_linux.zip entpacken && chmod u+x ngc && rm ngccli_cat_linux.zip ngc.md5 && echo “no-apikey nasciin” | ngc-Konfigurationsset

Nachdem NGC installiert ist, laden Sie ResNeXt-101_32x8d mit geringer Dichte im ONNX-Format herunter, indem Sie den folgenden Befehl ausführen:

ngc-Registrierungsmodell Download-Version nvidia/resnext101_32x8d_dense_onnx:1″

Um das ONNX-Modell in TensorRT zu importieren, klonen Sie das TensorRT-Repository und richten Sie die Docker-Umgebung ein, wie in der NVIDIA/TensorRT-Readme erwähnt.

Nachdem Sie sich im TensorRT-Stammverzeichnis befinden, konvertieren Sie das dünn besetzte ONNX-Modell mit trtexec in die TensorRT-Engine. Erstellen Sie ein Verzeichnis zum Speichern von Modell und Motor:

cd /workspace/TensorRT/ mkdir-Modell

Kopieren Sie das heruntergeladene ResNext ONNX-Modell in das Verzeichnis /workspace/TensorRT/model und führen Sie dann den trtexec-Befehl wie folgt aus:

./workspace/TensorRT/build/out/trtexec –onnx=/workspace/TensorRT/model/resnext101_32x8d_sparse_fp32.onnx –saveEngine=/workspace/TensorRT/model/resnext101_engine.trt –explicitBatch –sparsity= aktivieren –fp16

Eine neue Datei namens resnext101_engine.trt wird unter /workspace/TensorRT/model/ erstellt. Die Datei resnext101_engine.trt kann jetzt serialisiert werden, um Rückschlüsse mit einer der folgenden Methoden durchzuführen:

  • TensorRT-Laufzeit in C++ oder Python, wie in diesem Beispiel-Notebook gezeigt
  • NVIDIA Triton Inferenzserver

Leistung in TensorRT 8.0

Ein Benchmarking dieses spärlichen Modells in TensorRT 8.0 auf einer A100-GPU bei verschiedenen Chargengrößen zeigt zwei wichtige Trends:

  • Die Leistungsvorteile steigen mit dem Arbeitsaufwand des A100. Größere Losgrößen führen im Allgemeinen zu größeren Verbesserungen, die sich am oberen Ende 20 % nähern.
  • Bei kleineren Losgrößen, bei denen die Taktraten des A100 niedrig bleiben können, können sie durch Sparsity bei gleicher Leistung noch niedriger eingestellt werden, was zu einer Verbesserung der Energieeffizienz führt, die über der Leistung selbst liegt, was zu einer Leistung von bis zu 36 % pro Watt führt gewinnen.

Vergessen Sie nicht, dass dieses Netzwerk genau die gleiche Genauigkeit wie die dichte Basislinie hat. Diese zusätzliche Effizienz und Leistung erfordert keine benachteiligende Genauigkeit.

Ein Säulendiagramm, das die Inferenzleistung und die Leistungs-pro-Watt-Verbesserungen des spärlichen Netzwerks im Vergleich zu einem dichten Netzwerk über eine Reihe von Batchgrößen auf einer A100-GPU mit TensorRT 8.0 in fp16-Präzision zeigt.Abbildung 2. Sparsity-Verbesserungen bei Leistung und Energieeffizienz (mit Dichte als Basis)

Zusammenfassung

Sparsity ist in der Forschung zur Kompression und Vereinfachung neuronaler Netze beliebt. Bis jetzt hat die feinkörnige Sparsity ihr Leistungs- und Genauigkeitsversprechen jedoch nicht gehalten. Wir haben eine 2:4 feingranulare strukturierte Sparsity entwickelt und die Unterstützung direkt in NVIDIA Ampere Architecture Sparse Tensor Cores integriert. Mit diesem einfachen, dreistufigen Workflow für das spärliche Retraining können Sie spärliche neuronale Netze generieren, die der Grundgenauigkeit entsprechen, und TensorRT 8.0 beschleunigt sie standardmäßig.

Weitere Informationen finden Sie in der Sitzung „Making the Most of Structured Sparsity in the NVIDIA Ampere Architecture GTC2021“, in der alles über die Beschleunigung der Sparsity in der NVIDIA Ampere Architecture oder im Whitepaper Accelerating Sparse Deep Neural Networks.

Sind Sie bereit, einzusteigen und 2:4 Sparsity in Ihren eigenen Netzwerken auszuprobieren? Die PyTorch-Bibliothek Automatic SParsity (ASP) macht es einfach, ein Netzwerk mit geringer Dichte zu generieren, und TensorRT 8.0 kann sie effizient bereitstellen.

Weitere Informationen zu TensorRT 8.0 und seinen neuen Funktionen finden Sie in der Sitzung Beschleunigen von Deep Learning Inference with TensorRT 8.0 GTC’21 oder auf der TensorRT-Seite.