Heim >Technologie-Peripheriegeräte >KI >So optimieren Sie sehr große Modelle mit begrenzten GPU-Ressourcen

So optimieren Sie sehr große Modelle mit begrenzten GPU-Ressourcen

WBOY
WBOYnach vorne
2023-04-13 08:10:071558Durchsuche

So optimieren Sie sehr große Modelle mit begrenzten GPU-Ressourcen

Frage: Was soll ich tun, wenn die Modellgröße die GPU-Kapazität überschreitet?

Dieser Artikel ist inspiriert vom Kurs „Efficient Deep Learning Systems“, der von der Yandex School of Data Analysis angeboten wird.

Vorkenntnisse: Es wird davon ausgegangen, dass der Leser bereits versteht, wie die Vorwärts- und Rückwärtsbewegungen neuronaler Netze funktionieren, was für das Verständnis des Inhalts dieses Artikels von entscheidender Bedeutung ist. Dieser Artikel verwendet PyTorch als Framework.

Lasst uns anfangen!

Wenn Sie versuchen, ein großes Modell (auch bekannt als gpt-2-xl) zu verwenden, das über 500 Millionen Parameter enthält, und Ihre GPU-Ressourcen begrenzt sind, können Sie es nicht zur Ausführung auf der GPU oder während des Modelltrainings installieren Was soll ich tun, wenn die im Papier definierte Losgröße in diesem Zeitraum nicht erreicht werden kann? Möglicherweise können Sie aufgeben und eine leichtere Version des Modells verwenden oder die Größe des Trainingsstapels reduzieren, sodass Sie nicht die im Dokument beschriebenen Trainingsergebnisse erhalten.

Es gibt jedoch einige Techniken, die zur Lösung der oben genannten Probleme beitragen können.

Lassen Sie uns einige Methoden zur Feinabstimmung des GPT-2-XL-Modells mit 1,5 Milliarden Parametern besprechen.

Der Kern des Problems

Lassen Sie uns zunächst die Essenz des GPU-Speicherproblems verstehen, das zum Laden des Modells in die GPU erforderlich ist.

Unter der Annahme, dass das Modell über FP32-Parameter (32-Bit-Gleitkomma) verfügt, muss dieses Modell auf der GPU trainiert werden, indem beispielsweise der Adam-Optimierer ausgeführt wird.

Durch Berechnung sind die Ergebnisse schockierend.

So optimieren Sie sehr große Modelle mit begrenzten GPU-Ressourcen

Angenommen, Sie besitzen bereits eine NVIDIA GeForce RTX 3060 mit 12 GB Speicher. Erstens beanspruchen 1e9 FP32-Parameter etwa 4 GB GPU-Speicher.

Ebenso wird die gleiche Menge an Speicher für Farbverläufe reserviert. Daher wurden insgesamt 8 GB Speicher reserviert, da das Training noch nicht gestartet und der Optimierer nicht geladen wurde, erfordert das Laden des Optimierers auch eine gewisse Speichermenge. Der Adam-Optimierer muss die erste und zweite Sicherung für jeden Parameter speichern, was 8 GB zusätzlichen Speicher erfordert. Wenn Sie dies berechnen, müssen Sie über etwa 16 GB GPU-Speicher verfügen, um das Modell korrekt auf die GPU zu laden. In diesem Beispiel verfügt die GPU nur über 12 GB freien Speicher. Sieht schlecht aus, oder?

Es gibt jedoch einige Möglichkeiten, dieses Problem zu lösen. Hier sind die relevanten:

  • Gradientenakkumulation/Mikrobatchierung;
  • Gradienten-Checkpointing;
  • Modellparalleles Training;
  • Tensorparallelisierung
  • Gemischtes Präzisionstraining;
  • Speicherauslagerung
  • Optimierer 8-Bit-Quantisierung.
  • Als nächstes werden diese Technologien im Detail erläutert.
  • Start

Frage: Das Modell ist größer als die GPU-Kapazität, was soll ich tun?

  • Einfacher Modus: Chargengröße 1 kann nicht angepasst werden # 🎜🎜#
  • Professioneller Modus: Die Parameter können auch nicht angepasst werden
# 🎜 🎜#

Übersicht

Wenn das Modell größer als die GPU-Kapazität ist, reicht es nicht, die Stapelgröße auf 1 zu setzen genug, dann wird das Was tun? Es gibt eine Lösung: Schauen wir uns dieses Konzept an. Für ein einfaches vorwärtsgerichtetes neuronales Netzwerk mit n Schichten lautet das Gradientenberechnungsdiagramm wie folgt:

# Die Aktivierung von Die neuronale Netzwerkschicht entspricht dem mit f gekennzeichneten Knoten. Während des Vorwärtsdurchlaufs werden alle diese Knoten nacheinander berechnet. Die Verlustgradienten, die den Aktivierungen und Parametern dieser Schichten entsprechen, werden durch mit b gekennzeichnete Knoten dargestellt. Beim Rückwärtsdurchlauf werden alle diese Knoten in umgekehrter Reihenfolge ausgewertet. Die Berechnungsergebnisse von f-Knoten werden zur Berechnung von b-Knoten verwendet, sodass alle f-Knoten nach der Weiterleitung im Speicher verbleiben. Erst wenn die Backpropagation weit genug fortgeschritten ist, um alle Abhängigkeiten des Knotens f zu berechnen, kann er aus dem Speicher gelöscht werden. Das bedeutet: Der Speicherbedarf für die einfache Backpropagation wächst linear mit der Anzahl der neuronalen Netzwerkschichten n. So optimieren Sie sehr große Modelle mit begrenzten GPU-Ressourcen

Das Folgende ist die Berechnungsreihenfolge dieser Knoten. Der lila schattierte Kreis zeigt an, welcher Knoten zu einem bestimmten Zeitpunkt im Speicher gespeichert werden muss Zeit. .

# 🎜 🎜#gradientcheckpointSo optimieren Sie sehr große Modelle mit begrenzten GPU-Ressourcen

wie oben erwähnt Einfache Backpropagation ist rechnerisch optimal: Jeder Knoten wird nur einmal berechnet. Wenn Sie die Knoten jedoch neu berechnen, können Sie möglicherweise viel Speicher sparen. Beispielsweise kann jeder Knoten einfach neu berechnet werden. Die Ausführungsreihenfolge und der verwendete Speicher sind in der folgenden Abbildung dargestellt:

#🎜 🎜## 🎜🎜#Diese Strategie ist hinsichtlich des Gedächtnisses optimal. Beachten Sie jedoch, dass die Anzahl der Knotenberechnungen im Vergleich zum vorherigen Skalierungsfaktor n n²-mal skaliert wird: Jeder n-Knoten wird nacheinander n-mal neu berechnet. Aufgrund der langsamen Rechengeschwindigkeit ist diese Methode nicht für Deep Learning geeignet.

Um ein Gleichgewicht zwischen Speicher und Berechnung herzustellen, muss eine Strategie vorgeschlagen werden, die eine Neuberechnung von Knoten ermöglicht, jedoch nicht zu häufig. Eine hier verwendete Strategie besteht darin, eine Teilmenge der Aktivierungen neuronaler Netzwerke als Checkpoint-Knoten zu markieren. So optimieren Sie sehr große Modelle mit begrenzten GPU-Ressourcen

Wählen Sie in diesem Beispiel den quadrat(n)ten Knoten aus, der als markiert ist ein Kontrollpunkt. Auf diese Weise liegt die Anzahl der Checkpoint-Knoten und die Anzahl der Knoten zwischen Checkpoints zwischen sqrt(n), was bedeutet: Die benötigte Speichermenge skaliert ebenfalls in der Größenordnung von n. Die für diese Strategie erforderliche zusätzliche Berechnung entspricht der Berechnung, die für einen einzelnen Vorwärtsdurchlauf durch das Netzwerk erforderlich ist.

Routine: So optimieren Sie sehr große Modelle mit begrenzten GPU-Ressourcen

#🎜🎜 # Nachdem wir die Details des Gradienten-Checkpointing kennengelernt haben, wollen wir sehen, wie man dieses Konzept in PyTorch anwendet. Es sieht nicht allzu schwierig aus:

# 🎜🎜#

Gradientenakkumulation/Mikrobatching

So optimieren Sie sehr große Modelle mit begrenzten GPU-Ressourcen

Übersicht

Deep-Learning-Modelle werden immer größer und es ist schwierig, so große neuronale Netze in den GPU-Speicher zu integrieren. Daher sind Sie beim Training gezwungen, eine kleinere Batchgröße zu wählen, was zu einer langsameren Konvergenz und einer geringeren Genauigkeit führen kann.

Was ist Gradientenakkumulation?

Beim Training eines neuronalen Netzwerks werden die Daten normalerweise in Stapel unterteilt, und das neuronale Netzwerk sagt die Stapelbezeichnungen voraus, anhand derer der Verlust im Verhältnis zum tatsächlichen Ziel berechnet wird. Führen Sie als Nächstes einen Rückwärtsdurchlauf durch, um den Gradienten zu berechnen und die Modellgewichte zu aktualisieren. Die Gradientenakkumulation ändert den letzten Schritt des Trainingsprozesses: Bevor Sie mit dem nächsten Mini-Batch fortfahren, speichern Sie den Gradientenwert und fügen Sie den neuen Gradienten zum zuvor gespeicherten Gradienten hinzu, anstatt die Netzwerkgewichte für jeden Mini-Batch zu aktualisieren. Die Gewichte werden erst aktualisiert, nachdem das Modell mehrere Mini-Batches verarbeitet hat. Die Gradientenakkumulation simuliert eine größere Stapelgröße. Wenn Sie 64 Bilder in einem kleinen Stapel verwenden möchten und die Stapelgröße 8 überschreitet, wird ein „CUDA-Speicherfehler…“ gemeldet. In diesem Fall können Sie 8 Bildstapel verwenden und die Gewichte einmal aktualisieren, nachdem das Modell 64/8 = 8 Stapel verarbeitet hat. Wenn Sie jeden Gradienten aus diesen 8 Chargen akkumulieren, sind die Ergebnisse (fast) gleich und das Training kann durchgeführt werden!

Routine:

Eine Standard-Trainingsschleife ohne Gradientenakkumulation ist normalerweise:

So optimieren Sie sehr große Modelle mit begrenzten GPU-Ressourcen

In PyTorch kann die Gradientenakkumulation einfach durchgeführt werden. Nachdem das Modell die Mini-Batch-Verarbeitung mithilfe von „accumulation_steps“ abgeschlossen hat, kann die Optimierung durchgeführt werden. Sie können Accumulation_steps auch verwenden, um den laufenden Verlust entsprechend der Art der Verlustfunktion aufzuteilen:

So optimieren Sie sehr große Modelle mit begrenzten GPU-Ressourcen

Wirklich schön, oder? Der Gradient wird berechnet, wenn „loss.backward()“ aufgerufen wird, und von PyTorch akkumuliert, bis er gestoppt wird, wenn „optimierer.zero_grad()“ aufgerufen wird.

Wichtig

Einige Netzwerkarchitekturen verwenden dedizierte Batch-Operationen, wie z. B. BatchNorm, und bei Verwendung derselben Batch-Größe können die Ergebnisse leicht abweichen.

Gemischtes Präzisionstraining

Übersicht

Gemischtes Präzisionstraining bezieht sich auf die Konvertierung einiger oder aller FP32-Parameter in kleinere Formate wie FP16, TF16 (Gleitkomma). Tensor) oder BF16 (Gleitkommabytes).

Hauptvorteile

Die Hauptvorteile des gemischten Präzisionstrainings sind:

  • Reduzierter Speicherverbrauch;
  • höhere Rechengeschwindigkeit) technische Stärke oder weniger Kommunikationsnutzung);
  • Verwenden Sie dedizierte Hardware für schnellere Berechnungen.

Derzeit interessiert mich nur der erste Vorteil – die Reduzierung der Speichernutzung. Mal sehen, wie man das PyTorch-Modell verwendet, um dies zu erreichen.

Routine:

So optimieren Sie sehr große Modelle mit begrenzten GPU-Ressourcen

Als Ergebnis wurde das Modell nach Abschluss der .half()-Operation zweimal kleiner. Der Skalierungsverlust nach der Konvertierung des Modells in andere Formate (z. B. BF16, TF16) wird in einem nachfolgenden Artikel besprochen. Einige Vorgänge können im FP16 nicht abgeschlossen werden, z. B. Softmax. PyTorch kann Torch.autocast verwenden, um diese Sonderfälle zu behandeln.

8-Bit-Optimierer

Das Erhöhen der Modellgröße ist die Der beste Weg, mehr zu erreichen. Ein effektiver Weg, um optimale Leistung zu erzielen. Das Training großer Modelle erfordert jedoch das Speichern des Modells, der Gradienten und des Optimiererstatus (z. B. Adams exponentielle glatte Summe und die Summe der Quadrate früherer Gradienten), die alle in einer begrenzten Menge an verfügbarem Speicher gespeichert werden.

Downgrade des 32-Bit-Optimierers auf den 8-Bit-Optimierer, wodurch der Wertebereich von 2³² auf nur 2⁸= reduziert wird 256 hat einen großen Einfluss auf die vom Optimierer reservierte Speichermenge.

Die Forscher schlugen einen neuen 8-Bit-Adam-Optimierer vor: „Es werden 32 sein.“ -bit Die Leistung bleibt für einen Teil des ursprünglichen Speichers erhalten.

Der 8-Bit-Optimierer besteht aus drei Komponenten: (1) Quantisierung auf Blockebene, isoliert Ausreißer und verteilt Fehler gleichmäßig auf alle Bit; (2) Dynamische Quantisierung zur Quantisierung kleiner und großer Werte mit hoher Genauigkeit; (3) Stabile Einbettungsschicht zur Verbesserung der Stabilität des Worteinbettungsoptimierungsmodells.

Mit diesen Komponenten können Optimierungen direkt über den 8-Bit-Zustand durchgeführt werden. Quantisieren Sie den 8-Bit-Optimiererzustand auf 32 Bit, führen Sie die Aktualisierung durch und quantisieren Sie den Zustand dann zur Speicherung auf 8 Bit. Die 8-Bit-zu-32-Bit-Konvertierung erfolgt elementweise in Registern, ohne dass langsame Kopien in den GPU-Speicher oder zusätzlicher temporärer Speicher zur Durchführung der Quantisierung und Dequantisierung erforderlich sind. Für GPUs bedeutet dies, dass der 8-Bit-Optimierer schneller ist als der normale 32-Bit-Optimierer.

Werfen wir einen Blick auf die inspirierenden Ergebnisse nach der Verwendung von 8-bit Adam: #🎜🎜 #

So optimieren Sie sehr große Modelle mit begrenzten GPU-Ressourcen

Es ist ersichtlich, dass die Verwendung von quantisiertem Adam möglich ist Sparen Sie ca. 8,5 GB GPU-Speicher, sieht ziemlich toll aus!

Nachdem wir die Benutzerfreundlichkeit verstanden haben, schauen wir uns an, wie man es in Python implementiert.

Das von Facebook bereitgestellte Bitsandbytes-Paket ist ein leichter Wrapper für benutzerdefinierte CUDA-Funktionen, der den 8-Bit-Optimierer und die Quantisierungsfunktion kapselt kann verwendet werden, um die Verwendung von 8-Bit-Adam zu realisieren.

Routine:

#🎜🎜 # So optimieren Sie sehr große Modelle mit begrenzten GPU-Ressourcen

Wie oben erwähnt, ist die Verwendung des Quantisierungsoptimierers sehr einfach und die Ergebnisse sind gut.

Feinabstimmung von GPT-2-XL auf der GPU basierend auf allen oben genannten Methoden.

Nachdem Sie die oben genannten Methoden gemeistert haben, verwenden Sie diese Methoden schließlich, um praktische Probleme zu lösen und das GPT-2-XL-Modell mit 1,5 Milliarden Parametern zu analysieren Anpassungen. Anscheinend gibt es keine Möglichkeit, es auf eine NVIDIA GeForce RTX 3060-GPU mit 12 GB RAM zu laden. Listen Sie alle Methoden auf, die verwendet werden können:

  • Gradient Checkpoint;
  • Training mit gemischter Präzision (Ich habe einen Trick eingerichtet: Verwenden Sie zwei Beispiele desselben Modells. Laden Sie es zuerst mit .half auf die GPU und nennen Sie es gpu_model. Zweitens CPU, nennen Sie es cpu_model. Laden Sie nach der Auswertung des GPU-Modells den Gradienten von gpu_model in cpu_model, führen Sie „optimierer.step()“ aus und laden Sie die aktualisierten Parameter in gpu_model). Gradientenakkumulation, der Verlust muss durch den 8-Bit-Adam-Optimierer skaliert werden.
  • Verwenden Sie alle oben genannten Methoden und sehen Sie sich den Code an:
Nach der Verwendung aller oben genannten Methoden wurde die Feinabstimmung des 16-GB-GPT-2-XL-Modells implementiert die GPU. Verstanden!

Fazit

So optimieren Sie sehr große Modelle mit begrenzten GPU-Ressourcen

In diesem Blog wurden die Schlüsselkonzepte für eine effiziente Speichernutzung vorgestellt, die sich, wie oben erwähnt, für eine Vielzahl schwieriger Aufgaben eignet. Weitere Konzepte werden in den folgenden Artikeln besprochen. Vielen Dank, dass Sie sich die Zeit genommen haben, diesen Artikel zu lesen!

Das obige ist der detaillierte Inhalt vonSo optimieren Sie sehr große Modelle mit begrenzten GPU-Ressourcen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:51cto.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen