John hat bereits eine großartige Antwort geschrieben. Betrachten Sie diese Antwort als Erweiterung seiner.
Derzeit arbeite ich viel mit Compute-Shadern für verschiedene Algorithmen. Im Allgemeinen habe ich festgestellt, dass Compute-Shader viel schneller als ihre entsprechenden Pixel-Shader sein oder auf Feedback basierende Alternativen transformieren können.
Wenn Sie sich einmal mit der Funktionsweise von Computing-Shadern befasst haben, sind sie in vielen Fällen auch viel sinnvoller. Um Pixel-Shader zum Filtern eines Bildes zu verwenden, müssen Sie einen Framebuffer einrichten, Scheitelpunkte senden, mehrere Shader-Stufen verwenden usw. Warum sollte dies zum Filtern eines Bildes erforderlich sein? Das Rendern von Vollbild-Quads für die Bildverarbeitung ist meiner Meinung nach mit Sicherheit der einzige "gültige" Grund, diese weiterhin zu verwenden. Ich bin überzeugt, dass ein Neuling auf dem Gebiet der Compute-Grafik Compute-Shader für die Bildverarbeitung viel natürlicher geeignet sind als das Rendern auf Texturen.
Ihre Frage bezieht sich insbesondere auf die Bildfilterung, damit ich nicht zu viel auf andere Themen eingehen werde. In einigen unserer Tests können allein durch das Einrichten eines Transformations-Feedbacks oder das Umschalten von Framebuffer-Objekten zum Rendern in eine Textur Leistungskosten in der Größenordnung von 0,2 ms entstehen. Denken Sie daran, dass dies jegliches Rendern ausschließt! In einem Fall haben wir den exakt gleichen Algorithmus für die Berechnung von Shadern beibehalten und eine deutliche Leistungssteigerung festgestellt.
Bei der Verwendung von Compute-Shadern kann mehr Silizium auf der GPU für die eigentliche Arbeit verwendet werden. Alle diese zusätzlichen Schritte sind erforderlich, wenn Sie die Pixel-Shader-Route verwenden:
- Scheitelpunktassembly (Lesen der Scheitelpunktattribute, Scheitelpunktteiler, Typkonvertierung, Erweiterung auf vec4 usw.)
- Der Vertex-Shader muss geplant werden, egal wie minimal er ist
- Der Rasterizer muss eine Liste von Pixeln berechnen, um die Scheitelpunktausgaben zu schattieren und zu interpolieren (wahrscheinlich nur Texturkoordinaten für die Bildverarbeitung).
- Alle verschiedenen Zustände (Tiefentest, Alphatest, Schere, Mischen) müssen eingestellt und verwaltet werden
Sie könnten argumentieren, dass alle zuvor erwähnten Leistungsvorteile von einem intelligenten Treiber negiert werden könnten. Du hättest recht. Ein solcher Treiber könnte erkennen, dass Sie ein Quad im Vollbildmodus ohne Tiefenprüfung usw. rendern, und einen "schnellen Pfad" konfigurieren, der alle nutzlosen Arbeiten zur Unterstützung von Pixel-Shadern übergeht. Es würde mich nicht überraschen, wenn einige Treiber dies tun, um die Nachbearbeitung in einigen AAA-Spielen für ihre spezifischen GPUs zu beschleunigen. Sie können natürlich eine solche Behandlung vergessen, wenn Sie nicht an einem AAA-Spiel arbeiten.
Was der Treiber jedoch nicht tun kann, ist, bessere Parallelitätsmöglichkeiten zu finden, die die Compute-Shader-Pipeline bietet. Nehmen Sie das klassische Beispiel eines Gaußfilters. Mit Compute-Shadern können Sie Folgendes tun (Filter trennen oder nicht):
- Teilen Sie für jede Arbeitsgruppe das Sampling des Quellbilds auf die Größe der Arbeitsgruppe auf und speichern Sie die Ergebnisse im gemeinsamen Gruppenspeicher.
- Berechnen Sie die Filterausgabe anhand der im gemeinsamen Speicher abgelegten Probenergebnisse.
- Schreiben Sie in die Ausgabe-Textur
Schritt 1 ist hier der Schlüssel. In der Pixel-Shader-Version wird das Quellbild mehrmals pro Pixel abgetastet. In der Compute-Shader-Version wird jedes Quellentexel nur einmal in einer Arbeitsgruppe gelesen. Texture Reads verwenden normalerweise einen kachelbasierten Cache, aber dieser Cache ist immer noch viel langsamer als der gemeinsam genutzte Speicher.
Das Gauß-Filter ist eines der einfacheren Beispiele. Andere Filteralgorithmen bieten andere Möglichkeiten, um Zwischenergebnisse in Arbeitsgruppen mithilfe des gemeinsamen Speichers auszutauschen.
Es gibt jedoch einen Haken. Compute-Shader benötigen explizite Speicherbarrieren, um ihre Ausgabe zu synchronisieren. Es gibt auch weniger Schutzmaßnahmen gegen fehlerhafte Speicherzugriffe. Für Programmierer mit guten Kenntnissen in der parallelen Programmierung bieten Compute-Shader viel mehr Flexibilität. Diese Flexibilität bedeutet jedoch, dass es auch einfacher ist, Computing-Shader wie normalen C ++ - Code zu behandeln und langsamen oder falschen Code zu schreiben.
Verweise
- OpenGL Compute Shaders-Wiki-Seite
- DirectCompute: Optimierungen und Best Practices, Eric Young, NVIDIA Corporation, 2010 [pdf]
- Efficient Compute Shader-Programmierung, Bill Bilodeau, AMD, 2011? [pps]
- DirectCompute for Gaming - Laden Sie Ihre Engine mit Compute-Shadern auf, Layla Mah & Stephan Hodes, AMD, 2013, [pps]
- Compute Shader Optimierungen für AMD GPUs: Parallel Reduction, Wolfgang Engel, 2014