Loop-Leistung in einem Shader

11

Ich frage mich, wie ich eine dynamische Schleifenfunktion am besten in einen Shader integrieren kann.

Erstens scheinen dynamische Arrays nicht möglich zu sein. Ist es also besser, ein Array mit maximaler Größe zu erstellen und nur einen Teil davon zu füllen oder Arrays mit vordefinierten Größen zu definieren?

Was ist dann der beste Weg, um über dieses Array zu iterieren?

Ist es besser, eine ungerollte Schleife oder eine dynamische Schleife für 4 bis 128 Iterationen zu verwenden? Ich habe auch gesehen, dass es möglich ist, es auf eine maximal vordefinierte Anzahl von Iterationen abzuwickeln und es dann mit einer Bedingung wie zu stoppen if (i == myCurrentMaximumIterationNumber).

Matte
quelle
2
Was versuchst du mit dem Array und der Schleife zu tun? Ich frage, weil das für mich irgendwie wie ein XY-Problem klingt . Da die beste Möglichkeit, Bedingungen und Schleifen auf der GPU zu verwenden, darin besteht, sie nicht zu verwenden, gibt es in Ihrem Fall möglicherweise noch bessere Möglichkeiten, anstatt Arrays und Schleifen zu verwenden.
Nero
Ich implementiere einen Screenspace-Streueffekt unter der Oberfläche, der derzeit funktioniert. Aber ich habe einige Zweifel daran, wie ich den Kernel je nach Leistung verwende. Ich habe mich für eine maximale Arraygröße entschieden und nur einen Teil gefüllt und eine dynamische Schleife mit einer dynamischen Anzahl von Iterationen verwendet, die sich auf den aktuell verwendeten Array-Inhalt bezieht. Ich denke, dass es Dinge zu tun oder zu wissen gibt, wenn man Shader zum Beispiel nach Leistungen programmiert. Und meiner Meinung nach ist Loops ein allgemeines Leistungsthema, das möglicherweise einigen Regeln und möglicherweise "guten Praktiken" folgt, aber ich habe keine gute Antwort darauf gefunden.
MaT

Antworten:

6

Shader-Compiler sind äußerst aggressiv beim Abrollen, da frühe HW häufig keine Flusskontrolle hatten und die Kosten für neuere HW variieren können. Wenn Sie einen Benchmark haben, gegen den Sie aktiv testen, und eine Reihe relevanter Hardware, versuchen Sie Dinge, um zu sehen, was passiert. Ihre dynamische Schleife ist für Entwicklerinterventionen besser geeignet als eine statische Schleife. Es ist jedoch immer noch ein guter Rat, sie dem Compiler zu überlassen, es sei denn, Sie haben einen Benchmark zur Verfügung. Mit einem Benchmark lohnt sich die Erkundung (und macht Spaß).

Übrigens ist der größte Verlust bei einer dynamischen Schleife auf einer GPU, dass einzelne "Threads" in einer Wellenfront / einem Warp zu unterschiedlichen Zeiten beendet werden. Die Threads, die später gestoppt werden, zwingen alle, die vorzeitig beendet werden, NOPs auszuführen.

Verschachtelte Schleifen sollten sorgfältig durchdacht werden: Ich habe einen blockbasierten Entropiedecoder implementiert, der Läufe von Nullen codiert (für JPEG-ähnliche Komprimierung). Die natürliche Implementierung bestand darin, die Läufe in einer engen inneren Schleife zu dekodieren - was bedeutete, dass oft nur ein Thread Fortschritte machte; Durch Abflachen der Schleife und explizites Testen in jedem Thread, ob gerade ein Lauf dekodiert wurde oder nicht, habe ich alle Threads durch die Schleife mit fester Länge aktiv gehalten (die dekodierten Blöcke hatten alle die gleiche Größe). Wenn die Threads wie CPU-Threads wären, wäre die Änderung schrecklich gewesen, aber auf der GPU, auf der ich lief, konnte ich die Leistung um das Sechsfache steigern (was immer noch schrecklich war - es gab nicht genügend Blöcke, um die GPU zu beschäftigen - aber es war ein Proof of Concept).

Daniel M Gessel
quelle