Was ist am schnellste?
-
Danke für alle Tipps!
Also t ist der einzige Parameter der Funktion, quasi: float foo(float t) { ... }
Einer hat vorgeschlagen, dass ich es mit einem Profiler testen soll. Leider kenne ich mich da überhaupt nicht aus. Kann mir jemand einen guten und einsteigerfreundlichen Profiler für C++ (ich benutze Visual Studio 05, falls das ne Rolle spielt) empfehlen?
Danke
-
schneller schrieb:
Einer hat vorgeschlagen, dass ich es mit einem Profiler testen soll. Leider kenne ich mich da überhaupt nicht aus. Kann mir jemand einen guten und einsteigerfreundlichen Profiler für C++ (ich benutze Visual Studio 05, falls das ne Rolle spielt) empfehlen?
Wenn du einen AMD-Prozessor hast, ist AMD CodeAnalyst sehr zu empfehlen. Allerdings sind solche Mikrooptimierungen nicht immer ganz einfach zu profilen, ich würde mich da eher auf grössere Bottlenecks konzentrieren.

-
zeig mal den bisherigen code.
-
volkard schrieb:
zeig mal den bisherigen code.
So sieht der Code aus:
D3DXVECTOR3 HermiteCurve::interpolate(float t) const { assert(t>=0 && t<=1); float bf_1 = 2*t*t*t - 3*t*t + 1; // blending function 1 float bf_2 = -2*t*t*t + 3*t*t; float bf_3 = t*t*t - 2*t*t + t; float bf_4 = t*t*t - t*t; return bf_1 * p1 + bf_2 * p2 + bf_3 * r1 + bf_4 * r2; }Leider habe ich keinen AMD Prozessor, sondern einen Intel Core2Duo. Welchen Profiler nimmt man da am besten?
-
spantan würde mir so ein gefummel einfallen.
D3DXVECTOR3 HermiteCurve::interpolate(float t) const { assert(t>=0 && t<=1); float t2=t*t; float t3=t*t*t; float bf_4 = t3 - t2; // t3 - t2 float tmp_1 = bf_4 - t2; // t3 - 2*t2 float bf_3 = tmp_1 + t; // t3 - 2*t2 + t; float tmp_2 = tmp_1 + t3 - t2; // 2*t3 - 3*t2; float bf_2 = -tmp_2; // -2*t*t*t + 3*t*t; float bf_1 = tmp_2 + 1; // 2*t*t*t - 3*t*t + 1 // blending function 1 return bf_1 * p1 + bf_2 * p2 + bf_3 * r1 + bf_4 * r2; }aber keine ahnung, ob das schneller oder langsamer ist.
-
schneller schrieb:
Leider habe ich keinen AMD Prozessor, sondern einen Intel Core2Duo. Welchen Profiler nimmt man da am besten?
Nur um Zeit zu messen, brauchst du keinen Profiler. Da reichen dir auch betriebssystemabhängige Funktionen. Leider kenne ich mich mit denen zu wenig aus, da ich bisher immer plattformunabhängige Implementierungen innerhalb von Bibliotheken (z.B. SFML) verwendet habe.
Aber wie gesagt: Mikrooptimierungen sind nicht einfach zu profilen. Die Unterschiede zwischen den Messungen sind oft recht klein und können auch von vielen anderen Faktoren abhängen, zum Beispiel wie ausgelastet der Prozessor gerade ist. Wenn du ein wenig von Assembler verstehst, könntest du dir auch das kompilierte Programm anschauen.
-
darf man mal fragen wie du ohne profiles drauf gekommen bist, dass es genau die interpolate funktion viel zeit in deinem programm braucht?
-
amrande schrieb:
darf man mal fragen wie du ohne profiles drauf gekommen bist, dass es genau die interpolate funktion viel zeit in deinem programm braucht?
Seinen Ausgangspost habe ich jetzt eher als allgemeine Frage aufgefasst...
-
#include <iostream> #include <windows.h> using namespace std; int main() { LARGE_INTEGER start_ticks, ende_ticks, frequenz; double tick_diff = 0; start_ticks.QuadPart = 0; ende_ticks.QuadPart = 0; nochmal: cin.get(); QueryPerformanceCounter(&start_ticks); QueryPerformanceFrequency(&frequenz); for (int i = 0; i < 80000000; ++i) { // ... hier deinen code testen ob er lahm oder schnell ist ... } // ... Ende der Geschwindigkeits-Tests! QueryPerformanceCounter(&ende_ticks); tick_diff = ((double) ende_ticks.QuadPart - (double) start_ticks.QuadPart) / frequenz.QuadPart; cout << tick_diff << endl; goto nochmal;hinweis: nur auf release testen. debug gibt ganz andere ergebnisse
-
nochmal: // ... goto nochmal;Wieso das? Hier könnte man wirklich ohne Probleme eine Schleife verwenden.
-
Nexus schrieb:
nochmal: // ... goto nochmal;Wieso das? Hier könnte man wirklich ohne Probleme eine Schleife verwenden.
Endlosschleife, ohne goto - sehr schön!

-
Alter Schwede schrieb:
Endlosschleife, ohne goto - sehr schön!

Normalerweise hat die Schleife eine Abbruchbedingung.
Und ja, eine Endlosschleife ist immer noch besser als
goto, da weiss man wenigstens, was passiert. Man hat einen separaten Block mit eigenem Gültigkeitsbereich und kann das Verhalten des Programms überblicken. Es gibt schon wenige berechtigte Anwendungsbereiche fürgoto, aber sicher nicht in Situationen, in denen eine Schleife nur Vorteile hat.
-
@Nexus
goto gehoert zur Sprache - und es bereichert sie**.**
-
for (;;) { /*...*/ }ist viel hübscher als goto und labels...
-
Alter Schwede schrieb:
goto gehoert zur Sprache - und es bereichert sie**.**

Natürlich. Nebenbei gehören sowohl Casts von konstanten Klasseninstanzen zu Non-Const-Referenzen auf
double-Arrays als auch Zeiger mit siebenfacher Indirektion ebenfalls zur Sprache. Ich hoffe, du siehst den Punkt.
-
xBlackKnightx schrieb:
#include <iostream> #include <windows.h> using namespace std; int main() { LARGE_INTEGER start_ticks, ende_ticks, frequenz; double tick_diff = 0; start_ticks.QuadPart = 0; ende_ticks.QuadPart = 0; nochmal: cin.get(); QueryPerformanceCounter(&start_ticks); QueryPerformanceFrequency(&frequenz); for (int i = 0; i < 80000000; ++i) { // ... hier deinen code testen ob er lahm oder schnell ist ... } // ... Ende der Geschwindigkeits-Tests! QueryPerformanceCounter(&ende_ticks); tick_diff = ((double) ende_ticks.QuadPart - (double) start_ticks.QuadPart) / frequenz.QuadPart; cout << tick_diff << endl; goto nochmal;hinweis: nur auf release testen. debug gibt ganz andere ergebnisse
Damit misst du schnell Mist.
Der "hier deinen code testen" Bereich muss nämlich so ausgelegt sein, dass der Compiler ihn nicht wegoptimieren kann (ein paar Berechnungen, deren Ergebnis dann nirgends verwendet wird, sind nämlich im Release ganz schnell einfach nichtmehr da). Und auch keine Optimierungen vornehmen, die unter realen Einsatzbedingungen nichtmehr möglich wären. Aber auch keine "nicht-wegoptimier" Hilfskonstrukte enthält, die zuviel Optimierungen verhindern, oder einfach selbst zuviel Overhead machen.
Profilen ist eben nicht so einfach wie klein Erna sich das vorstellt.
Zum "richtig" Profilen muss man das fertige Programm profilen. Oder zumindest ausreichend grosse Programmabschnitte. Und das geht oft nur vernünftig ... mit einem Profiler

-
hustbaer schrieb:
Zum "richtig" Profilen muss man das fertige Programm profilen. Oder zumindest ausreichend grosse Programmabschnitte. Und das geht oft nur vernünftig ... mit einem Profiler

Und sag jetzt blos nicht alles andere wäre prem..opt..., sonst löscht dich volkard aus.
-
na gut das
"for (;;)"wird übernommen!
hustbaer schrieb:
Damit misst du schnell Mist.
Der "hier deinen code testen" Bereich muss nämlich so ausgelegt sein, dass der Compiler ihn nicht wegoptimieren kann (ein paar Berechnungen, deren Ergebnis dann nirgends verwendet wird, sind nämlich im Release ganz schnell einfach nichtmehr da). Und auch keine Optimierungen vornehmen, die unter realen Einsatzbedingungen nichtmehr möglich wären. Aber auch keine "nicht-wegoptimier" Hilfskonstrukte enthält, die zuviel Optimierungen verhindern, oder einfach selbst zuviel Overhead machen.
Profilen ist eben nicht so einfach wie klein Erna sich das vorstellt.
Zum "richtig" Profilen muss man das fertige Programm profilen. Oder zumindest ausreichend grosse Programmabschnitte. Und das geht oft nur vernünftig ... mit einem Profiler

naja das mag stimmen. Ich weiss nur nicht wie Compiler das wirklich "optimiert"
wenn ich die 3 hier teste
void strcpy1( char s1[], char s2[]) { int i; for( i = 0; s2[i] != '\0'; ++i) s1[i] = s2[i]; s1[i] = '\0'; } void strcpy2( char *s1, char *s2) { for( ; *s2 != '\0'; ++s1, ++s2) *s1 = *s2; *s1 = '\0'; } void strcpy3( char *s1, char *s2) { while( (*s1++ = *s2++) != '\0' ); }und dann noch ein normales strcpy testen. Ergebnis: strcpy1 geht bei mir am schnellsten. Warum optimiert der Compiler nicht so dass die anderen mindestens genauso schnell sind wie strcpy1 ? Vlt mag das auch von CPU abhängen. Man kann auch da gleich ganze Programmabschnitte in "hier deinen code testen" einfügen oder? Oder verschiedene Funktionen zusammenstellen, die ein Programm braucht, dann immer wieder in einer bestimmten Abfolge testen lassen. Die Abfolge wird durch die externe Datei bestimmt (heisst auf Deutsch ääh z.b. 3D-Weltdaten laden und die Funktionen für Vektoren, Perspektive usw berechnen werden in Geschwindigkeitstest gemessen.) - praktisch wie ein Benchmark, somit kann man sicherstellen, dass da nix optimiert wird, wenn unterschiedliche Weltdaten geladen werden. Aber gut ich gebe zu, ich habe so ein Profiler noch nie ausprobiert.
-
Konnte man sich den optimierten Code nicht nochmal ausgeben lassen? Wenn ja, wie? Würde mich mal interessieren wie der verschiedene Codezeilen zerbröselt.
-
Skalli schrieb:
Konnte man sich den optimierten Code nicht nochmal ausgeben lassen? Wenn ja, wie?
Du kannst dir den Assembler-Code anschauen. Wie, hängt von deinem Compiler ab.