Ich benutze CUDA seit einigen Wochen, habe aber einige Zweifel an der Zuordnung von Blöcken / Warps / Thread. Ich studiere die Architektur aus didaktischer Sicht (Universitätsprojekt), daher ist es nicht mein Anliegen, Spitzenleistungen zu erzielen.
Zunächst möchte ich verstehen, ob ich diese Fakten richtig verstanden habe:
Der Programmierer schreibt einen Kernel und organisiert seine Ausführung in einem Raster von Thread-Blöcken.
Jeder Block ist einem Streaming Multiprocessor (SM) zugeordnet. Einmal zugewiesen, kann es nicht auf eine andere SM migrieren.
Jeder SM teilt seine eigenen Blöcke in Warps auf (derzeit mit einer maximalen Größe von 32 Threads). Alle Threads in einem Warp werden gleichzeitig auf den Ressourcen des SM ausgeführt.
Die eigentliche Ausführung eines Threads wird von den im SM enthaltenen CUDA-Kernen ausgeführt. Es gibt keine spezifische Zuordnung zwischen Threads und Kernen.
Wenn ein Warp 20 Thread enthält, aber derzeit nur 16 Kerne verfügbar sind, wird der Warp nicht ausgeführt.
Wenn ein Block hingegen 48 Threads enthält, wird er in zwei Warps aufgeteilt und parallel ausgeführt, sofern genügend Speicher verfügbar ist.
Wenn ein Thread auf einem Kern startet, für den Speicherzugriff oder für eine lange Gleitkommaoperation blockiert ist, kann seine Ausführung auf einem anderen Kern fortgesetzt werden.
Sind sie korrekt?
Jetzt habe ich eine GeForce 560 Ti, die gemäß den Spezifikationen mit 8 SM ausgestattet ist, die jeweils 48 CUDA-Kerne enthalten (insgesamt 384 Kerne).
Mein Ziel ist es sicherzustellen, dass jeder Kern der Architektur die gleichen Anweisungen ausführt. Unter der Annahme, dass mein Code nicht mehr Register erfordert als die in jedem SM verfügbaren, stellte ich mir verschiedene Ansätze vor:
Ich erstelle 8 Blöcke mit jeweils 48 Threads, so dass jeder SM 1 Block zum Ausführen hat. In diesem Fall werden die 48 Threads im SM parallel ausgeführt (wobei alle für sie verfügbaren 48 Kerne ausgenutzt werden)?
Gibt es einen Unterschied, wenn ich 64 Blöcke mit 6 Threads starte? (Vorausgesetzt, sie werden gleichmäßig auf die SMs verteilt)
Wenn ich die GPU in geplante Arbeiten "eintauche" (z. B. 1024 Blöcke mit jeweils 1024 Threads erstellen), kann davon ausgegangen werden, dass alle Kerne zu einem bestimmten Zeitpunkt verwendet werden und dieselben Berechnungen durchführen (vorausgesetzt, die Threads) nie stehen bleiben)?
Gibt es eine Möglichkeit, diese Situationen mit dem Profiler zu überprüfen?
Gibt es eine Referenz für dieses Zeug? Ich habe den CUDA-Programmierleitfaden und die Kapitel zur Hardwarearchitektur in "Programmieren massiv paralleler Prozessoren" und "Design und Entwicklung von CUDA-Anwendungen" gelesen. aber ich konnte keine genaue Antwort bekommen.