PyTorch 2 GPU Performance Benchmarks

Seit seiner Veröffentlichung im Jahr 2016 hat sich PyTorch zu einem der beliebtesten Deep-Learning-Frameworks entwickelt. Es wurde vom AI Research (FAIR)-Team von Facebook entwickelt und hat sich seitdem aufgrund seiner Benutzerfreundlichkeit und umfassenden Unterstützung neuronaler Netzwerkarchitekturen bei Forschern und anderen Anwendern einen Namen gemacht. Es wurde seitdem für eine Vielzahl von Anwendungen - von der Bild- und Spracherkennung bis hin zur Verarbeitung natürlicher Sprache (NLP) und Reinforcement Learning - eingesetzt. Im September 2022 wurde PyTorch durch die neu gegründete PyTorch Foundation Teil der Linux Foundation.

Mit der Veröffentlichung von PyTorch 2.0 im März 2023 werden zum Zweck der Leistungssteigerung eine Reihe bedeutender Änderungen eingeführt, wie etwa dynamische Formen (dynamic shapes) und verteiltes Training (distributed training). Ein Haupt-Feature ist die Einführung von Torch.compile als Haupt-API für PyTorch 2.0. Diese Funktion umschließt ein Modell (wrapper) und gibt ein kompiliertes Modell mit gesteigerter Leistung zurück, das vollständig additiv und optional ist, wodurch PyTorch 2 abwärtskompatibel bleibt. In den meisten Fällen kann dies durch einfaches Hinzufügen einer einzigen Codezeile erreicht werden:

model = torch.compile(model)

In diesem Blogartikel wird der Leistungsunterschied von PyTorch 1 und PyTorch 2 analysiert und verglichen. Hierfür wurden die Modelle ResNet-50 und BERT für den Benchmark-Trainingsprozess verwendet. Im Folgenden werden sie neben weiteren wichtigen Begriffen für einen schnellen Einstieg kurz erklärt:

ResNet-50

ResNet (Residual Neural Network) gilt als eines der ersten echten Deep-Learning-Netzwerke und wurde erstmals 2015 zur Bildklassifizierung eingeführt. Es löste das Problem des verschwindenden/explodierenden Gradienten, das in zuvor verwendeten Perzeptron-Netzwerkstrukturen auftrat, wenn die Anzahl der Zwischenschichten erhöht wurde (siehe Deep Residual Learning for Image Recognition). Das charakteristische Merkmal von residualen Netzwerken ist die Verwendung von "Sprungverbindungen" ("skip connections") zwischen verschiedenen Schichten, wodurch einzelne Schichten übersprungen werden können. Dies ermöglicht die Bildung viel tieferer Netzwerke und löst das oben erwähnte Problem verschwindender/explodierender Gradienten. Die für unsere Benchmarks verwendete ResNet-50-Modellversion 1.5 besteht aus 48 Faltungsschichten sowie einer MaxPool- und einer Average-Pool-Schicht, also insgesamt 48+1+1=50 Schichten mit 25 Millionen Parametern. Da es in vielen Benchmarks verwendet wird, steht eine nahezu optimale Implementierung zur Verfügung, die die Leistung einer GPU ausreizt und es ermöglicht, die tatsächlichen Leistungsgrenzen der Hardware aufzuzeigen.

BERT

BERT steht für Bidirectional Encoder Representations from Transformers und ist ein 2018 von Google entwickeltes Deep-Learning-Modell für die Verarbeitung natürlicher Sprache. Es nutzt die Transformer-Architektur, um eine kontextsensitive Darstellung von Wörtern in einem Text zu lernen. BERT wurde an einer großen Menge unbeschriebenem (unlabeled) Text trainiert, um ein allgemeines Verständnis der natürlichen Sprache zu erlangen. Durch dieses Training kann BERT kontextspezifische Bedeutungen von Wörtern verstehen und mehrdeutige Ausdrücke unterscheiden. Das Besondere an BERT ist seine bidirektionale Modellierung. Im Gegensatz zu früheren Sprachmodellen, die nur die vorangehenden Wörter als Kontext betrachteten, modelliert BERT den Kontext bidirektional. Das bedeutet, dass BERT sowohl die vorangehenden als auch die nachfolgenden Wörter im Text verwendet, um die Bedeutung eines bestimmten Wortes zu verstehen.

Für unsere Benchmarks haben wir die beiden Varianten „BERT large cased“ und „BERT base cased“ verwendet. BERT large besteht aus 24 Schichten, 1024 hidden dimensions, 16 attention heads und insgesamt 335 Millionen Parametern, während BERT base aus 12 Layern, 768 Hidden Dimensions, 12 Attention Heads und 110 Millionen Parametern besteht. Beide Versionen unterscheiden zwischen Groß- und Kleinschreibung.

Stapelgröße bzw. Batch Size ('bs')

Einer der wichtigsten Metaparameter im Deep-Learning-Training ist die Batchgröße. Sie bezieht sich auf die Anzahl der Stichproben (samples) aus dem Datensatz, die jeweils in einer Trainingsiteration verarbeitet werden. Der Trainingsdatensatz wird in Stapel bzw. "Batches" unterteilt, die nacheinander durch das System propagiert werden, bis der gesamte Datensatz verarbeitet wurde, wodurch eine Epoche abgeschlossen wird. Bei kleinen Datensätzen, die vollständig in den GPU-Speicher passen, kann die Stapelgröße auch den gesamten Datensatz umfassen, was zu nur einem Durchlauf pro Epoche führt. Dies ist jedoch typischerweise nicht der Fall, weshalb es sinnvoll ist, den Datensatz in kleinere Batches aufzuteilen. In der Literatur wird Batch oft als Mini-Batch bezeichnet, um diesen vom gesamten Datensatz zu unterscheiden. Da die Modellgewichtungen basierend auf den Erkenntnissen aus dem aktuellen Stapel (batch) nach jeder Iteration aktualisiert werden, wirkt sich die Wahl der Stapelgröße auch auf die Trainingsergebnisse und die Systemleistung, also die Performance aus. 

In unseren Benchmark-Ergebnissen ist die für die jeweilige GPU verwendete Batchgröße mit „bs“ gekennzeichnet.

Numerische Genauigkeit: fp32/AMP

Die numerische Genauigkeit (numerical precision), mit der die Gewichtungen und zugehörigen Werte in Deep-Learning-Modellen berechnet werden, spielt eine wichtige Rolle im Trainingsprozess. Eine höhere Genauigkeit ermöglicht feinere Gewichtseinstellungen, erfordert aber auch mehr Speicher und verlangsamt die Berechnung. In unseren Benchmarks untersuchen wir die Leistung von "fp32"-Datentypen und Berechnungen, die die "Automatic Mixed Precision"-Technik verwenden.

Der Datentyp „fp32“ (floating point 32-bit) ist der am weitesten verbreitete Standard im Deep Learning. Er verwendet eine 32-Bit-Kodierung, bestehend aus 1 Bit für das Vorzeichen, 8 Bit für den Exponenten und 23 Bit für die Mantisse.

Automatic Mixed Precision (AMP) ist eine Technik, die in der Deep-Learning-Community immer beliebter wird. Sie beinhaltet die Verwendung unterschiedlicher numerischer Genauigkeiten (z. B. fp8, fp16, fp32 und fp64) während des Trainingsprozesses, um die Effizienz und Genauigkeit von Deep-Learning-Modellen zu verbessern. Die Idee hinter AMP ist, dass einige Teile des Modells empfindlicher auf numerische Genauigkeit reagieren als andere. Durch die Verwendung einer höheren Genauigkeit dort, wo es notwendig ist, und einer geringeren Genauigkeit, wo es weniger wichtig ist, können Berechnungen insgesamt schneller und effizienter durchgeführt werden, ohne die Genauigkeit des Modells zu beeinträchtigen. Die Implementierung von Automatic Mixed Precision kann jedoch komplex sein und erfordert häufig spezielle Hardwareunterstützung.

MultiGPU-Training

Um die Kapazität aller am Multi-GPU-Training beteiligten GPUs voll auszunutzen, wurde das DistributedDataParallel-Modul von PyTorch mit einem Sub-Prozess pro GPU verwendet, was zu einer deutlich besseren Leistung führte, als bei Verwendung von DataParallel, bei dem alle Berechnungen im selben Prozess stattfinden.

Testumgebung

Die Benchmarks wurden mit dem AIME Benchmark-Tool durchgeführt, das von GitHub (pytorch-benchmark) heruntergeladen werden kann. Folgende PyTorch-Versionen wurden mit Nvidia-GPUs getestet:

  • PyTorch 1.13.0a mit CUDA 11.8.89 und Python 3.8.13, erstellt von Nvidia mit Optimierungen für Nvidia GPUs
  • PyTorch 1.13.1 mit CUDA 11.7.99 und Python 3.8.10
  • PyTorch 2.0.0 mit CUDA 11.8.89 und Python 3.8.10
  • PyTorch 2.0.0 mit CUDA 11.8.89 und Python 3.8.10 unter Nutzung von torch.compile für das Modell
  • PyTorch 2.1.0 mit CUDA 11.8.89 und Python 3.10.12 unter Nutzung von torch.compile für das Modell

Die AMD GPUs wurden getestet mit:

  • PyTorch 1.13.1 mit ROCM 5.4.2 und Python 3.8.10
  • PyTorch 2.1.2 mit ROCM 6.1 und Python 3.10.14

Je nach GPU-Typ kamen zwei unterschiedliche AIME-Systeme zum Einsatz, da einige GPUs für Workstations geeignet sind, während andere, insbesondere solche mit passiver Kühlung, nur in Servern zum Einsatz kommen sollten.

Die folgenden GPUs wurden mit der AIME Workstation G400 getestet:

  • Nvidia Geforce RTX 4090
  • Nvidia Geforce RTX 3090
  • Nvidia Geforce RTX 3090 TI
  • Nvidia Geforce RTX 2080 TI
  • Nvidia RTX Geforce 4060 TI
  • Nvidia RTX A5000
  • Nvidia RTX A5500

Mit dem AIME Server A4000 wurden diese GPUs getestet:

  • Nvidia A100 40GB
  • Nvidia A100 80GB
  • Nvidia H100
  • AMD Instinct MI100
  • Nvidia Tesla V100
  • Nvidia RTX 6000 Ada
  • Nvidia RTX 5000 Ada
  • Nvidia RTX A6000

Benchmark-Ergebnisse

Die folgenden Balkendiagramme zeigen für jede dargestellte GPU die Trainingsleistung der Modelle für mehrere PyTorch-Versionen.

ResNet-50 Training mit fp32

ResNet-50, Datentyp fp32

ResNet-50 Training mit Automatic Mixed Precision

ResNet-50, automatic mixed precision

Bert Training mit fp32

BERT large cased, Datentyp fp32

Bert Training mit Automatic Mixed Precision

BERT large cased, automatic mixed precision

Aus den Diagrammen geht klar hervor, dass sich die Trainingsleistung bei allen Modellen auf allen GPUs durch den Einsatz von PyTorch 2 mit kompilierten Modellen deutlich verbessert hat - insbesondere bei den GPUs der neusten Generation. In einigen Fällen, z.B. mit der Nvidia A100 und dem BERT base cased Modell, verdreifacht sich die Leistung. Das oben erwähnte Versprechen, diese Beschleunigung mit nur einer zusätzlichen Zeile Code zu erreichen, wurde bei den von uns verwendeten Modellen ResNet und BERT eingehalten.

Pytorch Multi-GPU Training

Als Nächstes untersuchen wir die Leistung für Multi-GPU-Training mit Nvidia A100 40GB, Nvidia A100 80GB, Nvidia RTX 6000 Ada, Nvidia RTX 4090 und Nvidia RTX 5000 am Beispiel von ResNet-50 mit fp32-Präzision und BERT Base Cased mit AMP. Wie oben erwähnt wurde das Modul DistributedDataParallel von PyTorch verwendet.

Mit Resnet-50 liegt der Leistungsskalierungsfaktor zwischen 0,9 und 0,95, was bedeutet, dass jede zusätzliche GPU dem System zwischen 90 % und 95 % Einzel-GPU-Leistung hinzufügt. Ein ähnliches Verhalten wird beim BERT base cased Modell mit AMP beobachtet.

Zusammenfassung

Die Einführung von PyTorch 2 ermöglicht es, die Effektivität der eigenen Deep-Learning-Modelle zu optimieren und erhebliche Leistungssteigerungen zu erwirken.

💡
Mit Pytorch 2 torch.compile und Automatic Mixed Precision erzielt man aktuell die bestmögliche GPU-Leistung mit Pytorch.

Die Verwendung von PyTorch 2 steigert durch seine kompilierten Modelle die Leistung im Vergleich zu allen bisherigen Pytorch Versionen, auch im Vergleich zu speziellen NVIDIA optimierten Versionen, erheblich.

💡
Mit Multi-GPU-Training lässt sich die Leistung darüber hinaus linear skalieren.

Mit einem Skalierungsfaktor von 90-95 Prozent ist Multi-GPU-Training eine geeignete Möglichkeit bei Pytorch, die Leistung eines Deep Learning Servers zu skalieren.

Ein Updaten seiner Anwendung auf Pytorch 2.0 lohnt sich! Man bekommt, ohne größeren Aufwand, einen kostenlosen Performance-Boost bei allen aktuellen GPU Modellen geschenkt.