[!NOTE] Automatische Übersetzung Dieser Artikel wurde automatisch aus der englischen Originalversion übersetzt.
Skalierung großer Sprachmodelle Models: Mehr-GPU- und Mehrknotenstrategien, die in der Praxis funktionieren
Große Model Arbeitslasten überschreiten aus verschiedenen Gründen die Grenzen eines einzelnen GPU. Ein Trainingssatz kann an Speichermangel bezüglich des Optimierer-Zustands scheitern, ein anderer aufgrund langer Sequenzen im Bereich der Activations, und selbst ein passend dimensionierter Model kann sein Throughput Ziel verfehlen. Jedes Problem erfordert unterschiedliche Partitionierungs- und Kommunikationsmuster.
Dies ist eine praktische Übersicht über die wichtigsten Parallelisierungsstrategien sowie die dahinterstehenden Einschränkungen, unter Berücksichtigung der Erkenntnisse aus Hugging Face’s Leitfaden für Ultra-Scale-Anwendungen. Ziel ist es, aufzuzeigen, was jede Aufteilung bewirkt, welche Informationen sie übermittelt und ab wann Kombinationen erforderlich werden.
Zusammenfassung. Replizierter Datenparallelismus ermöglicht das Training von Throughput, sofern eine Replik ausreicht. Vollständig geschardeter Datenparallelismus teilt den Model-Zustand auf, führt jedoch zu zusätzlichen Operationen wie Parameter‑All‑Gather und Gradient‑Reduce‑Scatter. Tensor-, Pipeline-, Kontext- sowie Expertenparallelismus verteilen die Berechnungen der Schichten, die Tiefe, die Sequenzen sowie die MoE-Experten. Kombinieren Sie diese Ansätze erst, nachdem die begrenzenden Speicher- oder Kommunikationsbedingungen ermittelt wurden.
Dieser Leitfaden setzt voraus, dass Sie mit der Rückpropagierung, Transformer-Schichten sowie einem standardmäßigen PyTorch-Trainingszyklus vertraut sind.
Beginnen Sie mit zwei Speicherkapazitäten
Das Training und Inference weisen nicht denselben Ressourcenverbrauch auf.
training peak ≈ parameters
+ gradients
+ optimizer state
+ saved activations
+ temporary buffers
+ communication buffers
+ allocator headroom
inference peak ≈ resident weights
+ KV cache
+ runtime workspace
+ communication buffers
+ allocator headroom
Ein 70-Milliarden-Parameter-Model erfordert bereits für allein die BF16 Weights einen Mindestspeicherbedarf von 140 GB im Dezimalformat. Diese Zahl sagt jedoch wenig über den Trainingsprozess aus, bei dem Gradienten, der Zustand des Optimizers, die Master-Weights-Instanz sowie die Activations eine entscheidende Rolle spielen können. Ebenso gibt sie keine Aufschlüsse über die Größe der Serving, bei der Cache-Strategien, Sequenzlängen, Batch-Konkurrenz und die Quantization von Bedeutung sind.
Analysieren Sie die genaue Architektur, die Genauigkeit, die Sequenzlänge, die Mikrobatches, den Optimierer, die Strategie zur Erstellung von Checkpoints sowie Runtime. Erfassen Sie außerdem den maximalen verfügbaren und reservierten Speicherbedarf, Tokens pro Sekunde, die Dauer in Kernels sowie die Zeit, die im Rahmen von Collective-Operationen benötigt wird.
Jede parallele Dimension erfordert einen Kompromiss
Die relevante Frage lautet nicht „Welche Technik ist am besten?“ Sondern: „Welche Dimension des Tensor wird aufgeteilt, welcher Zustand repliziert und welches Kollektiv gelangt in den kritischen Pfad?“
| Strategie | Aufteilen | Primäre Entlastung | Eingeführte Kommunikation |
|---|---|---|---|
| Repliziertes Datenparallelismus | Batchverarbeitung | Training Throughput | Gradient-All-Reduce |
| vollständig geschardete Datenparallelität | Parameter, Gradienten sowie der Optimierer-Zustand innerhalb einer DP-Gruppe | Model – Zustandsmemorie | Parameter All-Gather, Gradient Reduce-Scatter |
| Tensorparallelität | Matrix oder Attention-Dimensionen innerhalb der Schichten | Schicht Weights und Activations | Kollektive innerhalb von Transformer-Blöcken |
| Pipeline Parallelität | Schichtgruppen | Model Tiefe und Zustand pro Phase | Punkt-zu-Punkt-Kommunikation Activations zusammen mit Scheduling-Bubbles |
| Kontextparallelität | Sequenzdimension | Lange-Sequenz-Activation-Speicher | Tausch von Schlüssel/Wert oder Attention innerhalb der Sequenzgruppe |
| Experte Parallelität | MoE Experten und routierte Prozesse Tokens | Expertenkapazität pro Rang | Token Verteilung und Kombination, in der Regel im All-zu-All-Verfahren |
Die Erleichterung des Speicherverbrauchs ist kein fester Multiplikator. Sie hängt vom Grad der Sharding-Struktur, von dem, was weiterhin repliziert wird, vom vorübergehenden, nicht-shardeten Zustand, von der Activation-Politik, vom Puffermaterial, von Ungleichgewichten sowie von den Puffern ab.
Reproduzierbare Datenparallelität: Throughput ohne Kapazitätsbeschränkung
Durch verteilten Datenparallelismus wird auf jedem Knoten eine vollständige Trainingskopie bereitgehalten. Jeder Knoten verarbeitet dabei einen eigenen Mikro-Batch, wobei die Gradienten vor dem Schritt des Optimizers synchronisiert werden.
Verwenden Sie diesen Ansatz, wenn der gesamte Trainingzustand mit ausreichend Puffer Platz findet und die globale Batch-Größe erweitert werden kann oder die Gradientenakkumulation angepasst werden muss. Seine Hauptvorteile liegen in der einfachen Semantik sowie in der gut ausgereiften Kombination aus rückwärtsgerichteter Berechnung und gruppiertem Gradientenabzug.
Das Hinzufügen von Rängen kann nachteilig sein, wenn die lokale Batch-Größe zu klein wird – in diesem Fall kann das Netzwerk den All-Reduce-Vorgang nicht verbergen, die Übertragung der Eingaben verzögert sich, oder die gewünschte Optimierungsbatch-Größe skaliert nicht ausreichend.
Vollständig geschardete Datenparallelität: Zustandsmerkmale für Kollektive
Der vollständig geschardete Datenparallelismus speichert die Parameter-, Gradienten- sowie Optimierer-Schardungen über eine Gruppe von Knoten verteilt. Die Parameter einer Schicht werden zur Berechnung zusammengeführt und können anschließend erneut aufgeteilt werden; die Gradienten hingegen werden wieder an ihre ursprünglichen Eigentümer zurückgesendet.
Die aktuelle Dokumentation zu PyTorch unterscheidet zwischen den Eigenschaften von FSDP2 fully_shard API aus der älteren Version FullyShardedDataParallel Wrapper. FSDP2 gruppiert die Kommunikation nach den Modulen, an die sie gerichtet ist. fully_shard Es wird eine bottom-up-Ansatzweise angewendet, wobei empfohlen wird, dass die Schichtgruppen die Kommunikation sowie die Berechnungen überschneiden dürfen.
from torch.distributed.fsdp import fully_shard
# Apply bottom-up: each block becomes a communication group.
for block in model.transformer.blocks:
fully_shard(block)
# Shard remaining root parameters such as embeddings and output projection.
fully_shard(model)
# Construct the optimizer after parameters have become sharded DTensors.
optimizer = AdamW(model.parameters(), lr=learning_rate)
Es handelt sich um einen strukturellen Entwurf und nicht um einen vollständigen Launcher. Die Device-Meshes, die gemischte Präzision, das Checkpointing, die Initialisierung, der Optimiererzustand sowie die verteilte Checkpoints müssen mit der Trainingsumgebung übereinstimmen.
Sharding ist vorteilhaft, wenn der Model-Zustand eine bindende Einschränkung darstellt und die Berechnung auf den jeweiligen Ebenen ausreicht, um einen erheblichen Teil des Gesamtverkehrs zu verbergen. Bei kleinen Models-Instanzen, langsamen Verbindungen, sehr kleinen Ebenen oder Layouts, bei denen die Shard-Gruppen eine ungünstige Topologiegrenze überschreiten, kann dies jedoch ein nachteiliger Kompromiss sein.
Tensorparallelität: Mathematik der Partitionierungsschicht
Tensorparallelität unterteilt die lineare Algebra innerhalb eines Layers – beispielsweise durch spaltenparallele und zeilenparallele Projektionen. Da teilweise erzielte Ergebnisse in Transformer-Blöcken zu Collectives führen, spielen Latency sowie die Bandbreite während der Vorwärts- und Rückwärtspropagierung immer wieder eine entscheidende Rolle.
Verwenden Sie diesen Ansatz, wenn eine Schicht oder ihr Activations nicht mehr passen, oder wenn die Matrizenmultiplikationen so groß sind, dass eine partitionierte Kernels im Vergleich zu einem einzelnen Rechenrang bessere Leistungen erbringt. Weisen Sie die tensorparallele Gruppe auf das schnellste verfügbare Kommunikationsdomänensystem zu und messen Sie anschließend die Ergebnisse. Ein hoher Grad kann dazu führen, dass jede lokale Matrix so stark verkleinert wird, bis die Kernel-Effizienz abnimmt, während die kollektiven Overhead-Kosten zunehmen.
Sequenzielle Parallelisierung wird häufig mit Tensorparallelisierung kombiniert, um die Wiederholung einiger Activation-Arbeiten zu vermeiden; sie unterscheidet sich von der Kontextparallelisierung bezüglich der gesamten Eingabesequenz des Model.
Pipeline Parallelität: Tiefe der Partitionierung und Scheduling-Zeit
Pipeline Parallelisierung verteilt verschiedene Schichtgruppen auf unterschiedliche Phasen und überträgt Activations zwischen diesen. Mikro-Batches sorgen dafür, dass die Phasen gleichzeitig ausgeführt werden können.
Es beseitigt den Zustand nach jeder Stufe Model und kann im Vergleich zu layerbasierten Tensor-Collective-Operationen den Datenverkehr über langsamere Grenzen verringern. Zu den damit verbundenen Kosten gehören „Bubbles“, Activation-Übertragungen, Ungleichgewichte zwischen den Stufen, eine komplexere Scheduling-Logik sowie schwierigere Prozesse beim Wiederherstellen des Zustands und beim Erstellen von Checkpoints.
Für einen einfachen, ausgewogenen Zeitplan im GPipe-Stil mit p Phasen und m Bei Mikrobatch-Verarbeitung beträgt der ideale Anteil an vorwärtsgerichteten Datenpaketen ungefähr:
(p - 1) / (m + p - 1)
Reale Zeitpläne können Varianten wie „eins-vorwärts/eins-rückwärts“, Interleaving oder „Null-Blase“ verwenden, wobei ungleiche Kosten pro Schicht einen dominierenden Einfluss auf die Formel ausüben können. Die Abgrenzungen der Phasen sollten anhand gemessener Zeiten und Speicherverbrauche festgelegt werden – und nicht anhand einer gleichmäßigen Anzahl von Schichten.
Kontextparallelität: Aufteilung langer Sequenzen Activations
Durch Kontextparallelismus wird die Sequenzdimension verteilt. Jeder Knoten besitzt einen Teil der Sequenz, während Attention die zur Beibehaltung der semantischen Vollständigkeit des Kontexts erforderlichen Informationen austauscht. Bei der Implementierung können Point-to-Point-Ringe, All-Gather-, All-To-All-Verfahren oder hierarchische Kombinationen genutzt werden.
Es verringert den Speicherverbrauch von Activation bei der Trainierung mit langen Kontexten, verteilt jedoch Weights auf die gesamte Kontextgruppe und führt zu Kommunikationskosten im Rahmen von Attention. Der Nutzen hängt vom Typ von Attention, der Anwendung von kausalem Masking, der Sequenzlänge, der Notwendigkeit erneuter Berechnungen sowie davon ab, wie sich die Kontextgruppen mit Tensor- und Datenparallelisierungsgruppen kombinieren.
Wählen Sie es nicht anhand eines universellen Schwellenwerts von 8K, 32K oder 100K aus. Analysieren Sie stattdessen den Speicherverbrauch von Activation sowie die Kommunikationsbelastung von Attention im Hinblick auf die konkrete Architektur.
Experte Parallelerität: ausschließlich für eine MoE-Architektur
Expertenparallelismus verteilt die Experten in Schichten des Mixture-of-Experts-Ansatzes. Der Router sendet Token-Repräsentationen an ausgewählte Experten und kombiniert deren Ergebnisse. Nur die ausgewählten Experten führen für jeden Token Berechnungen durch, doch die gesamte Anzahl der Experten Weights erfordert weiterhin Speicherplatz sowie eine geeignete Serving-Platzierung.
Es handelt sich dabei nicht um einen Optimierungsschalter für einen dichten Model. Vielmehr ist er Teil einer MoE-Architektur und sorgt für Lastverteilung, Kapazitätsmanagement, Token-Verbindungen im All‑to‑All‑Modus, Behandlung von abgebrochenen oder aufgefüllten Tokens-Paketen, Berücksichtigung von Nebenverlusten sowie Ausgleich von Ausfallmustern. Es sollten Tokens-Werte pro Experten, Routing-Entropiewerte, Kapazitätsüberschreitungen, Kommunikationszeiten sowie die Qualität der Übertragung entlang der jeweiligen Route erfasst werden.
Erstellen Sie eine Layout-Struktur aus der Topologie
Große Trainingsysteme kombinieren verschiedene Dimensionen miteinander. Die Gesamtgröße der Welt folgt in der Regel einem Produkt wie zum Beispiel:
world size = DP × TP × PP × CP
Expertenbasiertes Parallelisieren kann Dimensionen unterschiedlich teilen oder falten, weshalb man die von dem Framework unterstützte Gitterstruktur überprüfen sollte, anstatt blind Multiplikationen vorzunehmen.
Erstellen Sie die Struktur in dieser Reihenfolge:
- Zeichnen Sie die Kommunikationsdomänen: Verbindungen von GPU zu GPU, Switches, NUMA-Grenzen, das Knotennetzwerk, den Oversubscription-Faktor sowie die Speicherpfade.
- Platzieren Sie häufig vorkommende, Latency-empfindliche Strukturen – in der Regel TP – in der schnellsten geeigneten Domäne.
- Wählen Sie aus dem verbleibenden Kapazitäts- und Bandbreitenumfang entweder FSDP-Strukturen oder replizierte DP-Gruppen aus.
- Fügen Sie PP hinzu, wenn eine tiefe Platzierung oder der Cross-Domain-Verkehr Vorteile bringt, wobei dabei die gemessene Bearbeitungszeit sowie der Speicherverbrauch abgewogen werden müssen.
- Fügen Sie CP nur aufgrund von Sequenzbeschränkungen hinzu und EP ausschließlich aufgrund der spezialisierten Topologie des Model.
- Überprüfen Sie, ob Anzahl der Knotenköpfe, versteckte Dimensionen, Schichten, Experten, Batch-Einheiten sowie Sequenzen für das gewählte Mesh-Modell teilbar sind.
- Es existieren Benchmark mehrere gültige Mesh-Modelle; topologieorientierte Heuristiken wählen lediglich Kandidaten aus, nicht unbedingt den optimalen Lösungsweg.
Zwei Clustern mit derselben Anzahl an GPU können unterschiedliche Layouts bevorzugen, da die Linkbandbreite, die Switch-Hierarchie, die CPU-Verbindung sowie der Netzwerk-Wettbewerb variieren.
Das Training und Serving erfordern getrennte Entscheidungen
Inference enthält in der Regel weder Gradienten noch den Zustand des Optimizers, weshalb Trainingskonfigurationen im Stil von FSDP nicht automatisch übertragen werden.
Für Serving fragen Sie:
- Passt eine einzige Replik zu den Anforderungen hinsichtlich Weights, KV cache, des Arbeitsraums sowie der Zielkonkurrenz?
- Wird Throughput besser durch mehr unabhängige Repliken abgedeckt oder durch das Sharding einer einzigen Replik?
- Verringert TP die pro-Rank-Anzahl von Weight sowie den Cache-Druck ausreichend, um die Kosten für die Kommunikation zwischen den Schichten auszugleichen?
- Wird PP effizient für den Model sowie den Anfragescheduler unterstützt?
- Wie wirken sich Prefill und Decode unterschiedlich auf die Rechenleistung, die Speicherbreite sowie die Interkonnektierung aus?
- Was geschieht mit den Randwerten von Latency, wenn die Anfragen unterschiedliche Längen bei den Prompt sowie beim Ausgabeinhalt aufweisen?
Benchmark der vollständige Server inklusive des Schedulers. QuantizationKontextverteilung, Batching-Strategie sowie Verkehrsmuster. Training Tokens Pro Sekunde kann keine Vorhersage erfolgen. Serving Zeit bis zum ersten Mal Token oder zwischen-Token Latency.
Eine skalierbare Layout-Struktur objektiv bewerten
Für jeden Kandidaten erfassen Sie:
- Model, Code, Runtime, Kernels sowie Topologie-Identität
- globale und lokale Batch-Prozesse, Sequenzverteilung sowie Token-Zählungen
- maximale Speichernutzung nach Kategorien, sofern verfügbar
- nützliche Werte für Tokens pro Sekunde sowie die Model-FLOP-Nutzung bei konsequenter Berechnung
- aufgewendete Zeit bei Operationen wie AllReduce, AllGather, ReduceScatter, AllToAll und PointToPoint
- Eingabestopps, Checkpoint-Zeit, Verhalten bei Neustart sowie Verteilung von Verzögerungen
- Trainingsverlust oder Serving-Ausgabe-Parität im Vergleich zur Baseline
Vergleichen Sie bewusst schwaches und starkes Skalieren. Beim schwachen Skalieren nimmt die Gesamtarbeit mit der Anzahl der Reihen zunehmend zu, während beim starken Skalieren die Gesamtarbeit konstant bleibt. Ein Prozentsatz, der als „Skalierungsleistung“ bezeichnet wird, ist ohne diesen Nenner sowie eine Referenzbasis bedeutungslos.
Fazit
Parallelität stellt eine Zuordnung von einem gemessenen Bottleneck zu einer Tensor-Dimension sowie zu einem Kommunikationsmuster dar. Methoden wie Replikation, Sharding, Partitionierung von Schichten, Staging, Sequenzpartitionierung sowie die Einsetzung von Experten Routing beseitigen jeweils unterschiedliche Einschränkungen und führen zu verschiedenen Fehlerrichtungen.
Der Arbeitslast wird ein Inventar erstellt, die Topologie wird aufgebaut, gültige Meshes werden erzeugt und diese anschließend analysiert. Die optimale Anordnung ist jene, die ausreichend Puffer bietet und die für die tatsächlich ausgeführte Aufgabe notwendige Kommunikation auf ein Minimum reduziert.