Richtlinie gegen die Optimierung bedingter Verschiebungen in Shadern mit `mix()`+`step()`
(iquilezles.org)Einführung
- Dieser Artikel möchte mit verbreiteten Irrtümern über Verzweigungen auf GPUs aufräumen.
- Einige Lernwebsites verbreiten falsche Informationen, die hier korrigiert werden sollen.
Problem
- Es wird ein Codebeispiel gezeigt, das den ternären Operator verwendet, um bedingte Ausführung in GPU-Code zu implementieren.
- Manche schlagen als „Optimierung“ vor, dies durch arithmetische Operationen zu ersetzen, doch das beruht auf einem Missverständnis.
- Der ternäre Operator führt eine bedingte Verschiebung aus, die mit einfachen Bitoperationen implementiert wird.
- Echte Verzweigungen kommen in GPU-Code zwar vor, werden aber nicht für kleine Registerverschiebungen verwendet.
Probleme der falschen Optimierung
- Die vorgeschlagene Optimierung läuft in der Praxis sogar langsamer als der ursprüngliche Code.
- Die Funktion
step()ist mit dem ternären Operator implementiert und führt dadurch unnötige zusätzliche Multiplikationen und Additionen aus. - Im ursprünglichen Code wird der Wert direkt bedingt verschoben.
Analyse des Maschinencodes
- Am Maschinencode von AMD- und Microsoft-Compilern lässt sich bestätigen, dass die GPU keine Verzweigung ausführt.
- Stattdessen wird die bedingte Verschiebung mit Vergleichsoperationen und Bitmasken umgesetzt.
Fazit
-
Optimierungsvorschläge mit der Funktion
step()sind Fehlinformationen und sollten korrigiert werden. -
Diese Fehlinformation verbreitet sich seit über 20 Jahren und muss richtiggestellt werden.
-
Inigo Quilez – lernt seit 1994 Computergrafik.
1 Kommentare
Hacker-News-Kommentare
Ich bin ziemlich sicher, dass das Fazit des Artikels stimmt, aber die Argumentation wäre stärker, wenn die Codegenerierung für beide Versionen gezeigt würde, nicht nur für die bessere
Es wäre schön, wenn es eine gute Möglichkeit gäbe zu erkennen, in welchen Fällen
iftatsächlich einen echten Branch erzwingtmix/lerps verwenden, ist, dass sie zwar etwas Overhead in Kauf nehmen, aber Angst davor haben, einen Branch zu erzeugenv = x > y ? a : b;tatsächlich funktioniert, aber es ist beunruhigend, dassifeine Syntax ist, die manchmal ein Branch ist und manchmal nichtAuch dieser Artikel ist relevant: Falsche Ratschläge zum Schreiben von Branches auf GPUs richtigstellen
Ich frage mich, warum der Compiler nicht erkennt, dass die "optimierte" Version äquivalent ist
step()verstehen und die Fällestep()=0.0undstep()==1.0getrennt optimieren könnenIch bin selbst schon in dieses Problem gelaufen. Claude/ChatGPT schlagen das ebenfalls als Optimierung vor, aber es verschlechtert die Leistung
Ich frage mich, wie man erkennen kann, ob eine OpenGL-Funktion emuliert wird, statt eine grundlegende GPU-Funktion direkt aufzurufen
Beim Schreiben von Code braucht man Erfahrung, um sicher sein zu können, dass es keine bedingten Branches geben wird
Es wird erklärt, wie eine Variante der Funktion
mixfür Vektoren arbeitet