Tutorial 1: Programmoptimierungen
Willkommen zum ersten rand()-Tutorial von Kongo. Das erste Tutorial ist der Optimierung von Programmen gewidmet, um noch schnelleren Code zu schreiben. Bei irgendwelchen Fragen, Beschwerden, Wünschen (z.B. fürs nächste Tutorial) schreib an kongo@gmx.at. Wenn du für diese Kapitel noch Informationen hast und du denkst dir: "Das muss auch noch rein!", dann schreib mir. Ich werde dieses Tutorial dann nachbessern. Feedback ist Willkommen.
Jedes Spiel, das man programmiert, soll noch schneller und besser werden. Jedoch kann der Code den man selbst schreibt, schnell die Performance drücken. Wie kann man noch schnelleren Code schreiben? Dies sind nur Aufzählungen von Programmierkniffen, also probier einfach herum.
Mathematische Tricks
Misc
Zeiger-Dereferenzierung
Code wie dieser:
kann durch folgenden ersetzt werden:
Dadurch ersparst du dir die ganzen Zeiger Dereferenzierungen, die ja eigentlich unnötig sind.
Schnellere Klassen
Unser Beispiel für dieses Unterkapitel ist eine Klasse für Vektoren. Wir haben ein paar Operatoren überladen, einen Konstruktor, Kopierkonstruktor und einen Destruktor geschrieben.
So.. das erste was wir hier überlegen ist, brauchen wir den Destruktor? Der Compiler kann einen mindestens gleich schnellen Leer-Destruktor erstellen. Wir haben nichts, dass einen Destruktor benötigt. Des weiteren können wir versuchen die Operatorfunktionen schneller zu machen. Hier ein Beispiel für eine nicht sehr gut durchdachte Funktion des Operator +.
Hier gibt es sehr viel zu optimieren. Fangen wir einfach ganz oben an. Der Parameter wird per Wert übergeben. Daraus folgt, dass Speicher allokiert wird und der Kopierkonstruktor aufgerufen wird. Besser wäre es, eine Referenz auf den Vektor zu machen. Des weiteren haben wir eine Variable bereitgestellt, die die neuen Werte nimmt und dann wieder zurückgibt. Daraus folgt, dass wir erstens wieder einen Aufruf eines Konstruktors haben, obwohl wir die Werte ja sowieso ändern und zweitens wird am Schluß der Kopierkonstruktor aufgerufen, da retVec ja eine lokale Variable ist.
Unsere optimierte Funktion sieht wie folgt aus:
Zusätzlich haben wir einen neuen Konstruktor geschrieben, der die drei Werte annimmt. Wir ersparen uns in der optimierten Funktion drei Kopierkonstruktoraufrufe. Das ist zwar nicht viel Ersparnis im Großen, jedoch für eine so kleine Funktion kann dies eine große Zeitersparnis bedeuten.
SIMD
SIMD (oder auch Intel's Streaming SIMD Extensions) bedeutet Single Instruction Multiple Data. Also eine Instruktion, mehrere Daten. SIMD ist eine Erweiterung der Pentium-Prozessoren, durch die wir noch schnelleren Code schreiben können.
Mit den SIMD Extensions können wir zB. 4 Multiplikationen oder 4 Additionen auf einmal berechnen. Ein SIMD Register kann 4 floating-point Variablen beinhalten. Also können wir in ein Register einen ganzen Vektor laden, oder in vier Register eine ganze 4x4-Matrix.
Für eine Matrix*Matrix Funktion benötigen wir standardmäßig 64 Multiplikationen und 48 Additionen. Mit SIMD benötigen wir jedoch nur mehr 16 Multiplikationen und 12 Additionen. Dadurch ersparen wir uns sehr viel Zeit in der Berechnung für diese Matrix*Matrix Funktion.
Unter den Links ganz unten, findest du ein Tutorial für SIMD: 'An Optimized Matrix Library'.
Assembler Optimierungen
Unter Visual C++ (6.0) kann man sich den Assemblercode, den der Compiler erstellt, ausgeben lassen. Dadurch kann man untersuchen, wie genau und gut der Compiler arbeitet. Selbstgeschriebener Assemblercode ist immer schneller als jeder Compiler. Compiler können nicht so gut sein, dass sie das händische nacharbeiten ersetzen. Unter 'Optionen' -> 'Einstellungen' -> Reiter 'C/C++' kann man unter 'Typ der Listing-Datei:' den Typ der Ausgabedatei einstellen. Hier können wir Kombinationen von Assembler-, Maschinen- und Quellcode auswählen. Für jede Quelldatei (*.cpp) wird jetzt eben diese Datei zusätzlich erstellt.
Links
Jim Blinn's Corner: Optimizing C++ vector Expressions
An Optimized Matrix Library in C++
Cleaning Memory and Partial Register Stalls in Your Code
GameDev: Performance Programming Applied to C++
Flipcode Tutorial: Faster Vector Math Using Templates
Bücher
Dov Bulka, David Mayhew: Efficient C++ Performance Programming Techniques. Addison Wesley, ISBN 0-201-37950-3
Copyright (c) by Kongo
Bei Fragen, Beschwerden, Wünschen E-mail an kongo@gmx.at
Tutorial vom 26.06.2001