it-swarm.com.de

Streaming von Multiprozessoren, Blocks und Threads (CUDA)

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

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


Nach meinem derzeitigen Verständnis gibt es pro Multiprozessor 8 Cuda-Kerne. 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?

56
ExtremeCoder

Das Thread-/Block-Layout ist ausführlich in der CUDA-Programmieranleitung beschrieben. Insbesondere heißt es in Kapitel 4:

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 beendet werden, werden neue Blöcke auf den freigewordenen Multiprozessoren gestartet.

Jedes SM enthält 8 CUDA-Kerne, und gleichzeitig führen sie eine einzelne Warp von 32 Threads aus. Es werden also 4 Taktzyklen benötigt, um einen einzelnen Befehl für die gesamte Warp auszuführen. Sie können davon ausgehen, dass Threads in einem beliebigen Warp in einem Lock-Step ausgeführt werden. Um jedoch Warps synchronisieren zu können, müssen Sie __syncthreads() verwenden.

57
Edric

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

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

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

Eine Kette wird immer von 32 Fäden gebildet und alle Fäden einer Kette werden gleichzeitig ausgeführt. 

Um die volle Leistung einer GPU zu nutzen, benötigen Sie viel mehr Threads pro SM, als der SM über SP verfügt. Für jede Berechnungsfunktion gibt es eine bestimmte Anzahl von Threads, die sich jeweils in einem SM befinden können. Alle Blöcke, die Sie definieren, werden in eine Warteschlange gestellt und warten, bis ein SM die Ressourcen (Anzahl der SPs) frei hat. Dann werden diese geladen. Der SM beginnt, Warps auszuführen. Da ein Warp nur 32 Threads hat und ein SM beispielsweise 128 SPs hat, kann ein SM 4 Warps zu einem bestimmten Zeitpunkt ausführen. Die Sache ist, wenn die Threads Speicherzugriff haben, blockiert der Thread, bis seine Speicheranforderung erfüllt ist. In Zahlen: Eine arithmetische Berechnung des SP hat eine Latenz von 18-22 Zyklen, während ein nicht zwischengespeicherter globaler Speicherzugriff bis zu 300-400 Zyklen dauern kann. Das heißt, wenn die Threads eines Warp-Prozesses auf Daten warten, funktioniert nur eine Teilmenge der 128 SPs. Daher schaltet der Scheduler um, falls verfügbar, ein weiteres Warp auszuführen. Und wenn dieser Warp blockiert, führt er den nächsten aus 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 unwahrscheinlich, dass keine Arbeit für die SP vorliegt.

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

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

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

28
JoeFox

Der Compute Work Distributor plant einen Thread-Block (CTA) nur dann auf einem SM, wenn der SM über ausreichende Ressourcen für den Thread-Block verfügt (gemeinsam genutzter Speicher, Warps, Register, Barrieren, ...). Ressourcen auf Thread-Block-Ebene, wie beispielsweise gemeinsam genutzter Speicher, werden zugewiesen. Die Zuweisung erzeugt ausreichend Warps für alle Threads im Threadblock. Der Ressourcenmanager ordnet Warps mit round robin den SM-Partitionen zu. Jede SM-Subpartition enthält einen Warp-Scheduler, eine Registerdatei und Ausführungseinheiten. Sobald ein Warp einer Unterpartition zugewiesen wurde, verbleibt es auf der Unterpartition, bis es abgeschlossen ist oder von einem Kontextwechsel (Pascal-Architektur) abgelöst wird. Beim Kontextwechsel wird der Warp auf dieselbe SM-Warp-ID wiederhergestellt.

Wenn alle Threads in Warp abgeschlossen sind, wartet der Warp-Scheduler, bis alle ausstehenden Anweisungen des Warp abgeschlossen sind, und der Ressourcenmanager gibt die Ressourcen auf Warp-Ebene frei, die Warp-ID und 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 ist.

Sobald ein Warp einer Unterpartition zugeordnet ist und alle Ressourcen zugewiesen sind, wird der Warp als aktiv betrachtet, was bedeutet, dass der Warp-Scheduler den Zustand des Warp aktiv verfolgt. In jedem Zyklus bestimmt der Warp-Scheduler, welche aktiven Warps angehalten sind und welche zur Ausgabe einer Anweisung berechtigt sind. Der Warp-Scheduler wählt den in Frage kommenden Warp mit der höchsten Priorität aus und gibt 1-2 aufeinanderfolgende Anweisungen aus dem Warp aus. Die Regeln für die Doppelausgabe sind für jede Architektur spezifisch. Wenn ein Warp eine Speicherladung ausgibt, kann er unabhängige Anweisungen ausführen, bis er eine abhängige Anweisung erreicht. Der Warp wird dann als blockiert gemeldet, bis der Ladevorgang abgeschlossen ist. Gleiches gilt für abhängige mathematische Anweisungen. Die SM-Architektur ist so konzipiert, dass sowohl ALU- als auch Speicherlatenz durch Wechseln zwischen den Warps pro Zyklus ausgeblendet werden.

Diese Antwort verwendet nicht den Begriff CUDA-Kern, da dies ein falsches Denkmodell einführt. CUDA-Kerne sind Pipeline-Ausführungseinheiten für Gleitkomma-/Integer-Einheiten mit einfacher Genauigkeit. Die Ausgaberate und Abhängigkeitslatenz ist für jede Architektur spezifisch. Jede SM-Unterteilung und jedes SM verfügt über andere Ausführungseinheiten, darunter Lade-/Speichereinheiten, Gleitkommaeinheiten mit doppelter Genauigkeit, Gleitkommazahlen mit halber Genauigkeit, Verzweigungseinheiten usw.

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

Der Begriff Belegung ist das Verhältnis von aktiven Warps zu maximalen Warps auf einem SM. Kepler-Pascal-Architektur (außer GP100) verfügt über 4 Warp-Scheduler pro SM. Die minimale Anzahl der Warps pro SM sollte mindestens der Anzahl der Warp-Scheduler entsprechen. Wenn die Architektur eine abhängige Ausführungslatenz von 6 Zyklen aufweist (Maxwell und Pascal), würden Sie mindestens 6 Warps pro Scheduler benötigen, dh 24 pro SM (24/64 = 37,5% Auslastung), um die Latenz abzudecken. Wenn die Threads Parallelität auf Befehlsebene haben, kann dies reduziert werden. Nahezu alle Kernel geben variable Latenzanweisungen aus, beispielsweise Speicherladevorgänge, die 80-1000 Zyklen dauern können. Dies erfordert mehr aktive Warps pro Warp-Scheduler, um die Latenzzeit zu verbergen. Für jeden Kernel gibt es einen Kompromiss zwischen der Anzahl der Warps und anderen Ressourcen wie Shared Memory oder Registern. Es wird daher nicht empfohlen, die Belegung zu 100% zu belegen, da wahrscheinlich andere Opfer gefordert werden. Der CUDA-Profiler kann bei der Ermittlung der Befehlsausgaberate, der Belegung und der Abbruchgründe behilflich sein, um den Entwickler bei der Ermittlung dieser Balance zu unterstützen.

Die Größe eines Threadblocks kann sich auf die Leistung auswirken. Wenn der Kernel große Blöcke enthält und Synchronisationsbarrieren verwendet, können Barrierenstillstände ein Grund für den Stall sein. Dies kann durch Verringern der Verzerrungen pro Threadblock gemildert werden.

4
Greg Smith

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 von Warp abstrahiert wird). SM arbeitet immer am Warp von Threads (immer 32). Ein Warp funktioniert nur bei Thread aus demselben Block.
SM und Block haben beide Beschränkungen für die Anzahl der Threads, die Anzahl der Register und den gemeinsam genutzten Speicher.

0
liu km