Langsames, gleichmäßiges Array im Shader, das einen FPS-Abfall verursacht


7

Ich versuche, ein einheitliches Array von Matrizen in meinem Compute-Shader zu verwenden. Es ist jedoch sehr langsam. Ich habe es auf diese Codezeilen eingegrenzt:

uniform mat4 someMatrixArray[64]; 
...
vec4 result = vec4(0);
for (int i = 0; i < 2048; i++) {
    result += someMatrixArray[i%64][0] * 0.01;
}

Wenn ich nicht auf someMatrixArray zugreife, erhalte ich mehr als 700 fps. Beim Zugriff habe ich 10 fps. Hat jemand eine Idee, was das verursachen könnte? Könnte es ein Treiberproblem sein?

Ich habe bereits versucht, die Schleifen (via #pragma optionNV (unroll all)) abzuwickeln, aber das hat nicht geholfen. Ich verwende eine GTX670 mit den neuesten Treibern unter Windows 7.

Bearbeiten:

Die generierte Baugruppe für die innere Schleife lautet:

MAD.F R0.xyz, c[196], {0.0099999998, 0, 0, 0}.x, R0;

Anscheinend kann der Wert von resultstatisch bestimmt werden, ohne dass er im Shader ausgewertet werden muss. Warum nicht auf der CPU berechnen und den Endwert resultals Uniform an den Shader übergeben?
Nicolas Louis Guillemot

Dies ist nur mein Testfall :) Mein tatsächlicher Code sieht anders aus (ich versuche, gekachelte verzögerte Schattierung zu implementieren)
tobspr

Versuchen Sie die Ganzzahldivision anstelle der Float-Multiplikation und sehen Sie, welche Änderungen Sie erhalten: result += someMatrixArray[i%64][0] / 100;
Tom 'Blue' Piddock

1
@Blue Das wäre interessant, wenn das tatsächlich helfen würde. Der ARB-Befehlssatz scheint keine kombinierte Division / Addition zu haben, wie dies beim Multiplizieren / Addieren der Fall ist. Theoretisch würde es entweder in zwei Anweisungen aufgeteilt oder als Compileroptimierung in Multiplikation umgewandelt. Obwohl ich verrücktere Dinge gesehen habe, wäre es sicherlich nicht aus dem Bereich der Möglichkeiten heraus. Befehlssatz ist hier. renderguild.com/gpuguide.pdf
Evan

1
Wenn ich Sie wäre, würde ich etwas wie developer.nvidia.com/nvidia-visual-profiler verwenden, um Shader-Läufe zu profilieren, um festzustellen, ob Ihr Engpass von dieser einheitlichen variablen Position liest oder ob es einfach die Anzahl der ausgegebenen Taktzyklen ist Schleifen. Da jede Schleife auf einen einzelnen MAD-Befehl hinausläuft, der in dasselbe Register liest und ausschreibt, stehen die Chancen gut, dass er aus c [Index] liest oder einfach zu viele Iterationen.
Evan

Antworten:


1

Ja, der Zugriff auf den Speicher kann immer wesentlich langsamer sein als der Nichtzugriff auf den Speicher. Besonders in einer for-Schleife, die 2000 Mal in einem Shader ausgeführt wird.

Ich denke, dass es hier nichts besonders Überraschendes gibt - die Aufteilung der Aufgabe in kleinere Schritte, die jeweils parallel ausgeführt werden können, und die Verwendung kleinerer Datenmengen sollten auf jeden Fall helfen.


Ja, das habe ich auch herausgefunden :) Ich habe es in mehrere Durchgänge aufgeteilt, und jetzt funktioniert es
einwandfrei
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.