OpenGL.org 3Dsource.de: Infos rund um 3D-Computergrafik, OpenGL und VRML
space Telefon-Tarife space VDI - Arbeitskreis Fahrzeugtechnik space Beschallungsanlagen und Elektroakustik space Heise-News space

22 Performance

22.010 Was muss ich über Performance grundsätzlich wissen ?

Grundsätzliche Aussagen gibt das (englischsprachige) Buch OpenGL on Silicon Graphics Systems in den Kapiteln 11 bis 14, dass auf den Webseiten von SGI zu finden sein sollte. Auch wenn einige Informationen speziell auf SGI-Maschinen zugeschnitten sind, sind die meisten Hinweise allgemein für OpenGL-Programmierer sehr hilfreich.

Zunächst sollte man die echten Schwachstellen eines Programms eingrenzen: Am Beispiel einer Datenbank, die etwa 5% der Rechenzeit zum Durchsuchen des Datenbestands und 95% für die Weitergabe der Daten über das Netzwerk benötigt, gelingt es einem Programmierer, die Zeit zur Suche im Datenbestand um 50% zu reduzieren. Nach der Optimierung zeigt sich aber kein sichtbar schnellerer Programmlauf.

Auch wenn die Änderungen im Quellcode nicht viel Zeit in Anspruch nehmen, einen sichtbaren Erfolg bringt eine derartige Herangehensweise nicht. Die Lokalisierung der sogenannten Bottlenecks (=Flaschenhälse) muss also immer der erste Schritt der Optimierung sein.

Grafische Anwendungen sind in vielen Bereichen nur mit hohem Rechenaufwand realisierbar. Es lassen sich drei Kathegorien finden: CPU-Auslastung, Geometrie-Berechnung und Grafikkarte (CPU limited, geometry limited, fill limited).

Die CPU-Auslastung beschreibt zum einen die (fehlende) Rechengeschwindigkeit des Hauptprozessors, aber auch die unmittelbar damit zusammenhängenden Baugruppen des Rechners (Speicherbus, Cache, Hauptspeicher). Hier ist es möglich, leistungsfähigere Komponenten (schnellere CPU, mehr RAM) zu verwenden oder das Programm entsprechend weniger anspruchsvoll zu entwerfen.

Durch die Geometrie-Berechnung gebremst wird ein Programm, wenn die Matrizenoperationen (Transformationen, Clipping, Beleuchtung, Culling...) die meiste Rechenzeit beanspruchen. Auf preiswerteren Systemen wird diese Berechnung noch durch die CPU erledigt, so dass hier kein echter Unterschied zwischen dem CPU limited und geometry limited besteht. Erst bei Vorhandensein eines Geometrie-Prozessors auf der Grafikkarte macht diese Unterscheidung Sinn.

Eine durch die Grafikkarte gebremste Anwendung kann so viele Pixel in den Framebuffer schreiben, wie durch die CPU bzw. Geometrie-Berechnung bereitgestellt werden. Hier hilft es, die Anzahl der Pixel zu begrenzen (kleineres Fenster) oder die Pixel weniger aufwendig darzustellen (einfaches Shading etc.).

Gerade die letzte Engstelle ist leicht zu bestimmen: Erhöht sich die Framerate bei verkleinertem Fenster, ist die Anwendung meist fill limited.

Bleibt die Programmgeschwindigkeit annähernd gleich, liegt die Ursache in der CPU bzw. Geometrie-Berechnung. Zur weiteren Eingrenzung kann man eine vorausberechnete, statische Szene mehrfach darstellen. Erhöht sich die Framerate jetzt, wird der grösste Teil der Rechenleistung für Aufbereitung der Daten und nicht für die Transformation etc. verwendet. In diesem Fall muss also der Bereich des Programms optimiert werden, der sich noch nicht direkt mit der Darstellung sondern mit anderen Berechnungen beschäftigt.

Lassen sich CPU und fill limited ausschliessen, liegt der Flaschenhals des Programms in der Geometrie-Berechnung. Hier muss optimiert werden, entweder durch Mehrfachnutzung von Vertices (z.B. mit Triangle Strips) oder vereinfachter der Darstellung (weniger Lichtquellen, Vertices etc.).

22.020 Wie kann ich die Performance meines Programms bestimmen ?

Der übliche Weg besteht darin, die Systemzeit festzustellen, einige Frames ablaufen zu lassen und dann wiederum die Systemzeit abzufragen. Teilt man die Anzahl der Frames (kompletten Durchläufe einer Szene) durch die gemessene Zeit, ergibt sich der Vergleichswert in fps (frames per second). Je mehr Frames dargestellt werden konnten, desto genauer wird das Ergebnis.

Will man die Anzahl der dargestellten Primitive bzw. Dreiecke je Sekunde bestimmen, muss ein entsprechender Zähler installiert werden (was im Nachhinein ziemlich kompliziert werden kann). Besteht diese Absicht von Anfang an, sollte man das Programm schon entsprechend aufbauen.

Noch schwieriger wird die Anzahl der Pixel je Sekunde. Hier sollte nach Möglichkeit ein Primitive mit bekannter Anzahl an Pixeln zum Einsatz kommen und gezählt werden.

Es gibt aber auch freie Benchmark Programme im Netz, z.B. bringt GLUT 3.7 das Programm progs/bucciarelli/gltest mit oder man kann sich auf den Seiten der Standard Performance Evaluation Corporation umsehen.

22.030 Welches Primitive wird am schnellsten gerendert ?

GL_TRIANGLE_STRIP gilt als das am besten optimierte Primitive. Vorteile erzielt man aber nur dann, wenn das Programm im Bereich der Geometrie-Berechnung die längste Rechenzeit beansprucht.

22.040 Was für Nachteile haben redundante Aufrufe ?

Obwohl einige OpenGL Implementationen durch redundante Aufrufe nur wenig ausgebremst werden, sollte man diese grundsätzlich vermeiden. Ein tatsächliche Geschwindigkeitsverlust lässt sich weder genau abschätzen noch ausschliessen.

22.050 Ich nutze derzeit (n) Lichtquellen. Sobald ich (n+1) Lichtquellen einsetze, bricht die Geschwindigkeit meines Programms erheblich ein. Warum ?

Normalerweise wird nur ein Teil der maximal möglichen Lichtquellen in Hardware unterstützt. Bei (n+1) eingesetzten Lichtquellen hat man diese Grenze überschritten und OpenGL berechnet die Beleuchtung nur noch in Software. Kommt man nicht mit weniger Lichtquellen (n) aus, hilft nur noch eine leistungsfähigere Grafikkarte.

22.060 Ich nutze derzeit (n) Texturen. Sobald ich (n+1) Texturen einsetze, bricht die Geschwindigkeit meines Programms erheblich ein. Warum ?

Jede Grafikkarte hat nur einen begrenzten Texturspeicher. In dem angesprochenem Fall reicht der Texturspeicher zwar noch für (n) Texturen, (n+1) Texturen passen aber nicht mehr hinein. Jetzt beginnt die OpenGL, bestimmte Texturen von dem Texturspeicher der Grafikkarte in den Hauptspeicher des Rechners auszulagern. Dieser Vorgang (über den Speicherbus) ist langsam, genauso wie der Hauptspeicher selbst langsamer als der Speicher auf der Grafikkarte ist.

Hier sollte man versuchen, Texturen mit kleinerer Auflösung zu verwenden und gewisse Abstriche in der Bildqualität in Kauf zu nehmen.

22.070 Warum ist glDrawPixels() und glReadPixels() so langsam ?

Während die Geschwindigkeit des 2D-Pfads (also der angesprochenen Befehle) auf vielen teuren Systemen durchaus akzeptabel ist, wird insbesondere bei preiswerteren Karten auf eine entsprechende Optimierung aus Zeit- und Kostengründen meist verzichtet. Nimmt man den Stand Anfang 2000, kann man bei Grafikkarten unter 1.000 DM kaum eine Optimierung des 2D-Pfads erwarten.

Falls eure Grafikkarte eigentlich schnell genug sein sollte, aber trotzdem nicht den Erwartungen entspricht, kann man folgende Tipps versuchen:

Alle Statusvariablen von glPixelTransfer() sollten auf den Standardwerten bleiben. Das gleiche gilt für glPixelStore(), mit Ausnahme von GL_PACK_ALIGNMENT und GL_UNPACK_ALIGNMENT, deren Werte auf 8 gesetzt werden sollten. Die Datenfelder sind dann als Double-Word (8 Byte) bereitzustellen.

Die Parameter von glDrawPixels() und glReadPixels() sollten auch auf den genutzten Framebuffer abgestimmt werden. Ein 24-Bit Framebuffer mit weiteren 8-Bit Alpha (insgesamt also 32 Bit) erfordert dann als Parameter GL_RGBA (4 Komponenten) und GL_UNSIGNED_BYTE (mit jeweils 8 Bit). Wird auf eine derartige Abstimmung verzichtet, muss die OpenGL eine geeignete Umrechnung der Daten für die Übernahme in den Framebuffer vornehmen, was entsprechend aufwändig ist.

Vor allen Dingen sollte man aber nicht vergessen, dass das vorhandene System (Systembus, Speicher) keine unbegrenzte Geschwindigkeitssteigerung ermöglicht. Die Erwartungen sollten bei diesen Operationen also auch nicht zu hoch angesetzt werden.

22.080 Was bringt mehr Geschwindigkeit, relative oder absolute Koordinaten ?

Arbeitet man immer mit direkten Koordinaten (also im Weltkoordinatensystem), kann man auf viele Transformationen verzichten, der Rechenaufwand vermindert sich also. Andererseits lassen sich gleichartige Objekte in eigenen (relativen) Koordinaten (Modellkoordinatensystemen) mehrfach verwenden, also Speicherplatz sparen.

Ein Beispiel soll die Entscheidung erleichtern:
Angenommen sei die Darstellung eines Hotels, mit sehr vielen gleichartigen Räumen, Türen, Türknöpfen, Lampen etc. Eine Möglichkeit besteht nun darin, jedes Objekt nur einmal anzulegen und dann mit geeigneten Modelltransformationen an den gewünschten Platz zu verschieben. Der erforderliche Speicherplatz ist gering, der Rechenaufwand hoch.
Als Alternative kann man jedes Objekt einzeln darstellen, mit einer entsprechenden Anpassung der (jetzt absoluten) Koordinaten. Durch den deutlich verringerten Rechenaufwand ist zwar ein Performance-Schub zu erwarten, allerdings wird der Speicherverbrauch sehr hoch. Muss das System jetzt Speicher auf die Festplatte auslagern, wird die Gesamtperformance deutlich einbrechen, auch wenn zunächst Rechenzeit gespart werden konnte.

Insgesamt gesehen gibt es also keine eindeutige Antwort auf die Frage. Es hängt alles der jeweiligen Situation ab. Die beste Lösung lässt sich z.B. durch Benchmarking ermitteln.

22.090 Was ist schneller, Display Listen oder Vertex Arrays ?

Die Antwort hängt vom genutzten System ab.

Wird die Performance nicht durch die Geometrie-Berechnung vermindert (sondern durch CPU oder Pixelrate), ist ein Unterschied zwischen Display-Listen oder Vertex Arrays nicht zu erwarten.

22.100 Wie kann ich einzelne Dreiecke am besten zu Triangle Strips zusammenfassen ?

Wie schon in Frage 22.030 gesagt, stellt GL_TRIANGLE_STRIP das höchstoptimierte Primitive dar. Enthält das Programm einzelne Dreiecke, die auch gemeinsame Eckpunkte teilen, lassen sich diese meist auch als Triangle Strips zusammenfassen und so schneller darstellen.

Wie dieses Zusammenfassen realisiert werden kann, hängt aber von den jeweiligen Daten ab. Findet man keinen geeigneten Algorithmus, kann man auch entsprechende Tools im Internet suchen (z.B. STRIPE).

Seite durchsuchen nach:

Fragen oder Ideen an:
Thomas.Kern@3Dsource.de
Linux-Counter
(C) Thomas Kern