Streaming von Multiprozessoren, Blöcken und Threads (CUDA)

77

Welche Beziehung besteht zwischen einem CUDA-Kern, einem Streaming-Multiprozessor und dem CUDA-Modell von Blöcken und Threads?

Was wird auf was und was parallelisiert und wie abgebildet? und was ist effizienter, maximieren Sie die Anzahl der Blöcke oder die Anzahl der Threads?


Mein derzeitiges Verständnis ist, dass es 8 Cuda-Kerne pro Multiprozessor gibt. und dass jeder Cuda-Kern jeweils einen Cuda-Block ausführen kann. und alle Threads in diesem Block werden seriell in diesem bestimmten Kern ausgeführt.

Ist das richtig?

ExtremeCoder
quelle

Antworten:

69

Das Thread- / Block-Layout ist im CUDA-Programmierhandbuch ausführlich beschrieben . In Kapitel 4 heißt es insbesondere:

Die CUDA-Architektur basiert auf einem skalierbaren Array von Multithread-Streaming-Multiprozessoren (SMs). Wenn ein CUDA-Programm auf der Host-CPU ein Kernel-Grid aufruft, werden die Blöcke des Grids aufgelistet und an Multiprozessoren mit verfügbarer Ausführungskapazität verteilt. Die Threads eines Threadblocks werden gleichzeitig auf einem Multiprozessor ausgeführt, und mehrere Threadblöcke können gleichzeitig auf einem Multiprozessor ausgeführt werden. Wenn Thread-Blöcke enden, werden neue Blöcke auf den frei gewordenen Multiprozessoren gestartet.

Jeder SM enthält 8 CUDA-Kerne und führt zu jedem Zeitpunkt einen einzelnen Warp von 32 Threads aus. Es dauert also 4 Taktzyklen, um einen einzelnen Befehl für den gesamten Warp auszugeben. Sie können davon ausgehen, dass Threads in einem bestimmten Warp im Sperrschritt ausgeführt werden. Um jedoch über Warps hinweg zu synchronisieren, müssen Sie verwenden __syncthreads().

Edric
quelle
14
Nur eine Ergänzung: Auf neueren Geräten gibt es 32 (Compute Capability 2.0) oder 48 (2.1) CUDA-Kerne pro SM. Die tatsächliche Anzahl macht für die Programmierung keinen großen Unterschied, die Warp-Größe beträgt 32 und hat dieselbe Bedeutung (dh Ausführung im Sperrschritt).
Tom
8
Tatsächlich erhöht Compute Capability 3.0 (Kepler) jetzt die Anzahl der Kerne / SM enorm - auf 192!
Edric
3
Ich verstehe es immer noch nicht. Es ist also immer 1 Warp pro Kern und die Anzahl der Warps pro SM entspricht der Anzahl der Kerne pro SM? Und wie werden Thread-Blöcke auf Warps abgebildet? Bestehen Blöcke immer aus einer ganzen Anzahl von Warps? Wenn zum Beispiel jeder Block 3 Warps enthält, bedeutet das, dass ich 3 Kerne auf einem bestimmten SM verwende?
Matt J
Wikipedia sagt, dass jeder SM 32 CUDA-Kerne enthält.
Haccks
1
Die Anzahl der Cuda-Kerne in einem SM hängt von der GPU ab. In GTX 1060 habe ich beispielsweise 9 SMs und 128 Prozessoren (Cuda-Kerne) für jeden SM für insgesamt 1152 CUDA-Kerne.
Sgira
36

Für die GTX 970 gibt es 13 Streaming-Multiprozessoren (SM) mit jeweils 128 Cuda-Kernen. Cuda-Kerne werden auch als Stream-Prozessoren (SP) bezeichnet.

Sie können Gitter definieren, die Blöcke der GPU zuordnen.

Sie können Blöcke definieren, die Threads Stream-Prozessoren zuordnen (die 128 Cuda-Kerne pro SM).

Ein Warp wird immer von 32 Threads gebildet und alle Threads eines Warps werden gleichzeitig ausgeführt.

Um die volle Leistung einer GPU nutzen zu können, benötigen Sie viel mehr Threads pro SM als der SM über SPs verfügt. Für jede Rechenfunktion gibt es eine bestimmte Anzahl von Threads, die sich jeweils in einem SM befinden können. Alle von Ihnen definierten Blöcke werden in die Warteschlange gestellt und warten, bis ein SM über die Ressourcen verfügt (Anzahl der freien SPs). Anschließend wird sie geladen. Der SM beginnt mit der Ausführung von Warps. Da ein Warp nur 32 Threads hat und ein SM beispielsweise 128 SPs hat, kann ein SM 4 Warps gleichzeitig ausführen. Die Sache ist, wenn die Threads Speicherzugriff haben, wird der Thread blockieren, bis seine Speicheranforderung erfüllt ist. In Zahlen: Eine arithmetische Berechnung auf dem SP hat eine Latenz von 18 bis 22 Zyklen, während ein nicht zwischengespeicherter globaler Speicherzugriff bis zu 300 bis 400 Zyklen dauern kann. Dies bedeutet, wenn die Threads eines Warps auf Daten warten, würde nur eine Teilmenge der 128 SPs funktionieren. Daher wechselt der Scheduler, um einen weiteren Warp auszuführen, falls verfügbar. Und wenn dieser Warp blockiert, wird der nächste ausgeführt und so weiter. Dieses Konzept wird als Latenzverstecken bezeichnet. Die Anzahl der Warps und die Blockgröße bestimmen die Belegung (aus der Anzahl der Warps, die der SM ausführen kann). Wenn die Belegung hoch ist, ist es unwahrscheinlicher, dass für die SPs keine Arbeit vorhanden ist.

Ihre Aussage, dass jeder Cuda-Kern jeweils einen Block ausführt, ist falsch. Wenn Sie über Streaming-Multiprozessoren sprechen, können sie Warps von allen Threads ausführen, die sich in der SM befinden. Wenn ein Block eine Größe von 256 Threads hat und Ihre GPU 2048 Threads pro SM zulässt, hat jeder SM 8 Blöcke, aus denen der SM Warps zur Ausführung auswählen kann. Alle Threads der ausgeführten Warps werden parallel ausgeführt.

Zahlen zu den verschiedenen Rechenfunktionen und GPU-Architekturen finden Sie hier: https://en.wikipedia.org/wiki/CUDA#Limitations

Sie können ein Belegungsberechnungsblatt von Nvidia Belegungsberechnungsblatt (von Nvidia) herunterladen .

JoeFox
quelle
5

Der Compute Work Distributor plant einen Thread-Block (CTA) auf einem SM nur dann, wenn der SM über ausreichende Ressourcen für den Thread-Block verfügt (gemeinsamer Speicher, Warps, Register, Barrieren, ...). Ressourcen auf Thread-Blockebene, wie z. B. gemeinsam genutzter Speicher, werden zugewiesen. Die Zuweisung erzeugt ausreichend Warps für alle Threads im Threadblock. Der Ressourcenmanager weist den SM-Unterpartitionen Warps mithilfe von Round Robin zu. Jede SM-Unterpartition enthält einen Warp-Scheduler, eine Registerdatei und Ausführungseinheiten. Sobald ein Warp einer Unterpartition zugeordnet ist, bleibt er auf der Unterpartition, bis er abgeschlossen ist oder von einem Kontextwechsel (Pascal-Architektur) vorbelegt wird. Bei der Wiederherstellung des Kontextschalters wird der Warp auf dieselbe SM-Warp-ID zurückgesetzt.

Wenn alle Threads in Warp abgeschlossen sind, wartet der Warp-Scheduler auf den Abschluss aller ausstehenden Anweisungen des Warps. Anschließend gibt der Ressourcenmanager die Ressourcen auf Warp-Ebene frei, die die Warp-ID und die Registerdatei enthalten.

Wenn alle Warps in einem Thread-Block abgeschlossen sind, werden Ressourcen auf Blockebene freigegeben und der SM benachrichtigt den Compute Work Distributor, dass der Block abgeschlossen wurde.

Sobald ein Warp einer Unterpartition zugewiesen ist und alle Ressourcen zugewiesen sind, wird der Warp als aktiv betrachtet, was bedeutet, dass der Warp-Scheduler den Status des Warps aktiv verfolgt. In jedem Zyklus bestimmt der Warp-Scheduler, welche aktiven Warps blockiert sind und welche zur Ausgabe einer Anweisung berechtigt sind. Der Warp-Scheduler wählt den Warp mit der höchsten Priorität aus und gibt 1-2 aufeinanderfolgende Anweisungen aus dem Warp aus. Die Regeln für die doppelte Ausgabe sind für jede Architektur spezifisch. Wenn ein Warp eine Speicherlast ausgibt, kann er weiterhin unabhängige Befehle ausführen, bis er einen abhängigen Befehl erreicht. Der Warp wird dann als blockiert gemeldet, bis der Ladevorgang abgeschlossen ist. Gleiches gilt für abhängige mathematische Anweisungen. Die SM-Architektur wurde entwickelt, um sowohl die ALU- als auch die Speicherlatenz zu verbergen, indem pro Zyklus zwischen Warps gewechselt wird.

In dieser Antwort wird der Begriff CUDA-Kern nicht verwendet, da dies ein falsches mentales Modell einführt. CUDA-Kerne sind Pipeline-Gleitkomma- / Ganzzahl-Ausführungseinheiten mit einfacher Genauigkeit. Die Ausgaberate und die Abhängigkeitslatenz sind für jede Architektur spezifisch. Jede SM-Unterpartition und SM verfügt über andere Ausführungseinheiten, einschließlich Lade- / Speichereinheiten, Gleitkommaeinheiten mit doppelter Genauigkeit, Gleitkommaeinheiten mit halber Genauigkeit, Verzweigungseinheiten usw.

Um die Leistung zu maximieren, muss der Entwickler den Kompromiss zwischen Blöcken und Warps und Registern / Thread verstehen.

Der Begriff Belegung ist das Verhältnis von aktiven Warps zu maximalen Warps auf einem SM. Die Kepler-Pascal-Architektur (außer GP100) verfügt über 4 Warp-Scheduler pro SM. Die minimale Anzahl von Warps pro SM sollte mindestens der Anzahl von Warp-Schedulern entsprechen. Wenn die Architektur eine abhängige Ausführungslatenz von 6 Zyklen hat (Maxwell und Pascal), benötigen Sie mindestens 6 Warps pro Scheduler, dh 24 pro SM (24/64 = 37,5% Belegung), um die Latenz abzudecken. Wenn die Threads Parallelität auf Befehlsebene aufweisen, kann dies verringert werden. Fast alle Kernel geben Anweisungen mit variabler Latenz aus, z. B. Speicherladevorgänge, die 80 bis 1000 Zyklen dauern können. Dies erfordert mehr aktive Warps pro Warp-Scheduler, um die Latenz zu verbergen. Für jeden Kernel gibt es einen Kompromiss zwischen der Anzahl der Warps und anderen Ressourcen wie gemeinsam genutztem Speicher oder Registern. Daher wird eine Optimierung für eine 100% ige Belegung nicht empfohlen, da wahrscheinlich ein anderes Opfer gebracht wird. Der CUDA-Profiler kann dabei helfen, die Gründe für die Ausgabe von Anweisungen, die Belegung und den Stillstand zu ermitteln, um dem Entwickler bei der Ermittlung dieses Gleichgewichts zu helfen.

Die Größe eines Gewindeblocks kann die Leistung beeinträchtigen. Wenn der Kernel große Blöcke hat und Synchronisationsbarrieren verwendet, können Barrierenstillstände ein Grund für das Stillstand sein. Dies kann durch Reduzieren der Verwerfungen pro Fadenblock verringert werden.

Greg Smith
quelle
-1

Auf einem Gerät befinden sich mehrere Streaming-Multiprozessoren.
Ein SM kann mehrere Blöcke enthalten. Jeder Block kann mehrere Threads enthalten.
Ein SM hat mehrere CUDA-Kerne (als Entwickler sollten Sie sich nicht darum kümmern, da es durch Warp abstrahiert wird), die für Threads funktionieren. SM arbeitet immer am Verziehen von Fäden (immer 32). Ein Warp funktioniert nur bei Threads aus demselben Block.
SM und Block haben beide Grenzen für die Anzahl der Threads, die Anzahl der Register und den gemeinsam genutzten Speicher.

liu km
quelle