Es war einmal, als> schneller war als <… Warten Sie, was?

280

Ich lese gerade ein großartiges OpenGL-Tutorial . Es ist wirklich toll, vertrau mir. Das Thema, an dem ich gerade bin, ist Z-Puffer. Neben der Erklärung, worum es geht, erwähnt der Autor, dass wir benutzerdefinierte Tiefentests wie GL_LESS, GL_ALWAYS usw. durchführen können. Er erklärt auch, dass die tatsächliche Bedeutung von Tiefenwerten (die oben sind und welche nicht) auch sein kann angepasst. Ich verstehe soweit. Und dann sagt der Autor etwas Unglaubliches:

Der Bereich zNear kann größer sein als der Bereich zFar; Wenn dies der Fall ist, werden die Fensterraumwerte in Bezug auf das, was dem Betrachter am nächsten oder am weitesten entfernt ist, umgekehrt.

Früher wurde gesagt, dass der Fensterraum-Z-Wert von 0 am nächsten und 1 am weitesten ist. Wenn jedoch unsere Clip-Space-Z-Werte negiert würden, wäre die Tiefe von 1 der Ansicht am nächsten und die Tiefe von 0 am weitesten. Wenn wir jedoch die Richtung des Tiefentests umkehren (GL_LESS zu GL_GREATER usw.), erhalten wir genau das gleiche Ergebnis. Es ist also wirklich nur eine Konvention. In der Tat war das Umdrehen des Z-Zeichens und des Tiefentests einst eine wichtige Leistungsoptimierung für viele Spiele.

Wenn ich es richtig verstehe, ist das Umdrehen des Vorzeichens von Z und des Tiefentests nichts anderes, als einen <Vergleich in einen >Vergleich umzuwandeln. Also, wenn ich das richtig verstanden , und der Autor nicht lügt oder Dinge zu machen, dann Wechsel <zu >verwendenden eine wichtige Optimierung für viele Spiele.

Erfindet der Autor Dinge, verstehe ich etwas falsch oder ist es tatsächlich so, dass es einmal <langsamer war ( lebenswichtig , wie der Autor sagt) als >?

Vielen Dank für die Klärung dieser ziemlich merkwürdigen Angelegenheit!

Haftungsausschluss: Mir ist völlig bewusst, dass die Komplexität von Algorithmen die Hauptquelle für Optimierungen ist. Außerdem vermute ich, dass es heutzutage definitiv keinen Unterschied machen würde und ich bitte dies nicht, um etwas zu optimieren. Ich bin nur extrem, schmerzhaft, vielleicht unerschwinglich neugierig.

Armen Tsirunyan
quelle
6
Der Link zu diesem Tutorial scheint (vor kurzem) tot zu sein. :(
TZHX
@TZHX: Da die akzeptierte Antwort vom Autor des Tutorials verfasst wurde, hoffen wir, sie wieder zu finden. Siehe meinen letzten Kommentar zu seiner Antwort :)
Armen Tsirunyan
3
Das OpenGL-Tutorial, auf das verwiesen wird, finden Sie hier .
Fons
(a <b) ist identisch mit (b> a), so dass es absolut nicht erforderlich ist, beide Vergleichsoperationen in Hardware zu implementieren. Der Leistungsunterschied ergibt sich aus dem, was als Ergebnis der Vergleichsoperation geschieht. Dies ist ein langer und kurvenreicher Weg, um alle Nebenwirkungen zu erklären, aber hier sind einige Hinweise. Spiele zum Füllen des Tiefenpuffers, um eine teurere Fragmentverarbeitung für Fragmente zu vermeiden, bei denen der Tiefentest fehlgeschlagen ist. Quake teilte den Tiefenbereich in zwei Hälften, um das Löschen des Bildpuffers zu vermeiden, da das Spiel immer jedes Pixel auf dem Bildschirm ausfüllte und so weiter.
T0rakka
2
@ Fons sieht aus wie der Link wieder tot :(
Nalzok

Antworten:

350

Wenn ich die Leistung richtig verstehe, ist das Umdrehen des Vorzeichens von Z und des Tiefentests nichts anderes als das Ändern eines <Vergleichs zu einem> Vergleich. Wenn ich also richtig verstehe und der Autor nicht lügt oder sich etwas ausdenkt, war das Ändern von <auf> für viele Spiele eine wichtige Optimierung.

Das habe ich nicht besonders gut erklärt, weil es nicht wichtig war. Ich fand es einfach eine interessante Kleinigkeit, etwas hinzuzufügen. Ich hatte nicht vor, den Algorithmus speziell durchzugehen.

Der Kontext ist jedoch der Schlüssel. Ich habe nie gesagt, dass ein <Vergleich schneller ist als ein> Vergleich. Denken Sie daran: Es handelt sich um Tiefenprüfungen der Grafikhardware, nicht um Ihre CPU. Nicht operator<.

Ich bezog mich auf eine bestimmte alte Optimierung, bei der Sie einen Frame GL_LESSmit einem Bereich von [0, 0,5] verwenden würden. Das nächste Bild rendern Sie GL_GREATERmit einem Bereich von [1.0, 0.5]. Sie gehen hin und her und "drehen buchstäblich das Vorzeichen von Z und den Tiefentest um" jedes Bild.

Dies verliert ein bisschen an Tiefengenauigkeit, aber Sie mussten den Tiefenpuffer nicht löschen, was früher eine ziemlich langsame Operation war. Da Tiefenreinigung heutzutage nicht nur kostenlos, sondern auch schneller als diese Technik ist, tun es die Leute nicht mehr.

Nicol Bolas
quelle
1
Der Grund, warum das Löschen des Tiefenpuffers heutzutage schneller ist, hat zwei Gründe, die beide auf der Tatsache beruhen, dass die GPU einen hierarchischen Tiefenpuffer verwendet. Daher muss nur gelöscht werden, um die Kachelzustände zu löschen (was schnell ist). Das Ändern des Tiefenvergleichszeichens bedeutet jedoch, dass der gesamte HiZ-Puffer geleert werden muss, da je nach Vergleichszeichen nur ein Min- oder Max-Wert gespeichert wird.
Jasper Bekkers
3
@NicolBolas: PerTZHXs Kommentar, der Link zu Ihrem Tutorial in meiner Frage ist tot. Könnten Sie uns bitte alle mitteilen, wohin die Tutorials verschoben wurden, und die Frage optional bearbeiten?
Armen Tsirunyan
2
Die Tutorials sind im Webarchiv verfügbar. Wenn @NicolBolas dies zulässt, wäre es für die Community hilfreich, wenn wir sie an einen zugänglicheren Ort verschieben könnten. Vielleicht GitHub oder so. web.archive.org/web/20150215073105/http://arcsynthesis.org/…
ApoorvaJ
3

Die Antwort ist mit ziemlicher Sicherheit, dass das hierarchische Z für jede Inkarnation von Chip + Treiber nur in die eine Richtung funktionierte - dies war damals ein ziemlich häufiges Problem. Low-Level-Assemblierung / Verzweigung hat nichts damit zu tun - Z-Pufferung erfolgt in Hardware mit festen Funktionen und wird per Pipeline übertragen - es gibt keine Spekulationen und daher keine Verzweigungsvorhersage.

Crowley9
quelle
0

Eine solche Optimierung beeinträchtigt die Leistung vieler eingebetteter Grafiklösungen, da dadurch die Auflösung von Framebuffern weniger effizient wird. Das Löschen eines Puffers ist ein klares Signal an den Treiber, dass er den Puffer beim Binning nicht speichern und wiederherstellen muss.

Wenig Hintergrundinformationen: Ein Kachel- / Binning-Rasterisierer verarbeitet den Bildschirm in einer Anzahl sehr kleiner Kacheln, die in den On-Chip-Speicher passen. Dies reduziert Schreib- und Lesevorgänge in den externen Speicher, wodurch der Verkehr auf dem Speicherbus verringert wird. Wenn ein Frame abgeschlossen ist (Swap wird aufgerufen oder FIFOs werden geleert, weil sie voll sind, sich die Framebuffer-Bindungen ändern usw.), muss der Framebuffer aufgelöst werden. Dies bedeutet, dass jeder Behälter nacheinander verarbeitet wird.

Der Treiber muss davon ausgehen, dass der vorherige Inhalt erhalten bleiben muss. Die Aufbewahrung bedeutet, dass der Behälter in den externen Speicher geschrieben und später aus dem externen Speicher wiederhergestellt werden muss, wenn der Behälter erneut verarbeitet wird. Die Löschoperation teilt dem Fahrer mit, dass der Inhalt des Fachs gut definiert ist: die klare Farbe. Dies ist eine Situation, deren Optimierung trivial ist. Es gibt auch Erweiterungen, um den Pufferinhalt zu "verwerfen".

t0rakka
quelle
-8

Es hat mit Flag-Bits in hoch abgestimmten Baugruppen zu tun.

x86 hat sowohl jl- als auch jg-Anweisungen, aber die meisten RISC-Prozessoren haben nur jl und jz (kein jg).

Joshua
quelle
2
Wenn das die Antwort ist, wirft es neue Fragen auf. Wurde "Verzweigung genommen" auf frühen RISC-Prozessoren langsamer als "Verzweigung ignoriert"? Soweit ich weiß, ist das jetzt auf keine messbare Weise so. Sollten Sie dann forSchleifen mit einer bedingungslosen Verzweigung rückwärts und einer bedingten, selten genommenen Verzweigung vorwärts schreiben , um die Schleife dann zu verlassen? Klingt unangenehm.
Pascal Cuoq
54
-1: Diese Frage hat nichts mit CPUs zu tun . GL_LESS und GL_GREATER sind Tiefenvergleichsoperationen, die auf GPUs ausgeführt werden.
Nicol Bolas
8
Komisch, wie viel Wiederholung Sie für eine Antwort bekommen können, die dem Titel entspricht, aber sehr wenig mit der eigentlichen Frage zu tun hat.
Joshua
7
+1 Nein, diese Antwort ist zumindest für einen Teil der Frage richtig. Die Frage ist: "Erfindet der Autor Dinge, missverstehe ich etwas oder ist es tatsächlich so, dass einmal <langsamer war (lebenswichtig, wie der Autor sagt) als>?". Es gibt drei Möglichkeiten. Diese Antwort reagiert auf die Möglichkeit von Option 3. Nirgendwo in dem Artikel wird die Technologie der CPU / GPU angegeben, noch muss es sich um eine GPU handeln (erste 3D-Spiele, bei denen CPU vorhanden ist). Ok ... ich glaube nicht, dass es viele 3D-Spiele auf RISC gab :-)
xanatos
3
(und das GPU-Tag wurde um 20:34
Uhr