Benchmark float/int
-
Hallo zusammen
Ich habe mir spasseshalber ein Progrämmchen in C++ geschrieben, um die floating-point und Integer Rechenleistung meines betagten 550MHz Athlons zu messen. Für die Messung musste der Computer, für verschiedene Datentypen, die vier Grundrechenoperationen in einem Loop ausführen. Für das folgende Ergebnis wurden die Loops 100Mio mal durchlaufen:
char performance = 727.273 MIOPS
short performance = 1025.64 MIOPS
int performance = 727.273 MIOPS
long performance = 1052.63 MIOPS
float performance = 1025.64 MFLOPS
double performance = 1052.63 MFLOPS
long double performance = 1025.64 MFLOPSInteressant finde ich, dass die Rechnungen mit char und int besonders langsam sind, jedoch die Berechnungen mit double sowie long double nicht langsamer als die mit float. Es würden mich eure Meinungen/Ideen dazu interessieren.

#include <cstdlib> #include <ctime> #include <iostream> #include <fstream> using namespace std; // stopwatch class class Stopwatch { public: void Start(void); void Stop(void); double Show(void); private: clock_t m_start_time; clock_t m_stop_time; }; void Stopwatch::Start(void) { m_start_time = clock(); } void Stopwatch::Stop(void) { m_stop_time = clock(); } double Stopwatch::Show(void) { return (double)(m_stop_time - m_start_time) / CLOCKS_PER_SEC; } // benchmark template template <class T> double Benchmark(unsigned long loops) { Stopwatch sw; sw.Start(); T n; for(unsigned long i = 0; i < loops; ++i) { n = 2; n *= 4; n += 7; n /= 3; n -= 1; } sw.Stop(); // MFLOPS return ((loops * 4) / sw.Show()) / 1000000; } // main program int main(int argc, char *argv[]) { fstream file("./benchmark.txt", ios::out); file << "char performance = " << Benchmark<char>(100000000) << " MIOPS" << endl; file << "short performance = " << Benchmark<short>(100000000) << " MIOPS" << endl; file << "int performance = " << Benchmark<int>(100000000) << " MIOPS" << endl; file << "long performance = " << Benchmark<long>(100000000) << " MIOPS" << endl; file << "float performance = " << Benchmark<float>(100000000) << " MFLOPS" << endl; file << "double performance = " << Benchmark<double>(100000000) << " MFLOPS" << endl; file << "long double performance = " << Benchmark<long double>(100000000) << " MFLOPS" << endl; file.close(); system("PAUSE"); return EXIT_SUCCESS; }
-
Stöffel schrieb:
Interessant finde ich, dass die Rechnungen mit char und int besonders langsam sind...
in der tat sehr merkwürdig.
in der 'benchmark' funktion wird ja mit konstanten gerechnet, änder' das mal in irgendwas variables, damit dein compiler das nicht optimieren kann...
-
olaf@pc:~/test$ g++ test.cpp
olaf@pc:~/test$ ./a.out
char performance = 177.778 MIOPS
short performance = 177.778 MIOPS
int performance = 198.02 MIOPS
long performance = 190.476 MIOPS
float performance = 216.216 MFLOPS
double performance = 209.424 MFLOPS
long double performance = 45.4545 MFLOPS
olaf@pc:~/test$ g++ -O3 test.cpp
olaf@pc:~/test$ ./a.out
char performance = inf MIOPS
short performance = inf MIOPS
int performance = inf MIOPS
long performance = inf MIOPS
float performance = inf MFLOPS
double performance = inf MFLOPS
long double performance = inf MFLOPSdu wirst mit deinem programm keine brauchbaren ergebnisse erzielen, es kommt halt ganz drauf an was dein compiler alles so optimiert.
-
Du solltest mindestens 2 Modifikationen machen:
-
Ermittle den Wert von "loops" zur Laufzeit - lies den aus einem Textfile oder sowas. So dass der Compiler den Wert zur Compilezeit eben nicht wissen kann. Das sorgt schonmal dafür dass das Ergebnis der Schleife nicht zur Compilezeit ermittelt werden kenn.
-
Übergib das Ergebnis einer Funktion die der Compiler nicht kennt bzw. nicht wegoptimieren kann. Dazu eignet sich unter Windows z.B. WriteDebugString oder du kannst den Wert auch einfach mit ausgeben lassen (in das Textfile/den cout Stream/...). Das sorgt dafür dass der Compiler nicht die ganze Berechnung aus der Schleife rausnehmen kann, weil das Ergebnis ja verwendet wird.
Das Programm so wie es ist würde dir ein wirklich guter Compiler "zu nichts" optimieren

EDIT: genau das hat der gcc mit -O3 anscheinend gemacht.
-
-
Hmja, ein Ergebnis von Unendlich spricht wohl schon dafür, dass der ganze Loop wegoptimiert wurde. Ich hatte gehofft dass der Compiler nicht clever genug ist, um zu sehen dass die Berechnungen eigentlich überflüssig sind. Ich werde mal einen Versuch machen, wo die Variable einen zufälligen Anfangswert hat und nicht in jedem Loopdurchlauf neu initialisiert wird und das Resultat dann auch zurück gegeben wird. Mal sehen. Danke für eure Antworten.

-
schaltet doch einfach die Optimierung aus
-
Das macht den Vergleich aber nicht unbedingt deutlich aussagekräftiger. Tests sollten unter möglichst realen Bedingungen laufen. Keine Optimierungen ist imho nicht sehr real

-
TactX schrieb:
Das macht den Vergleich aber nicht unbedingt deutlich aussagekräftiger. Tests sollten unter möglichst realen Bedingungen laufen. Keine Optimierungen ist imho nicht sehr real

naja, aber in dem fall will er ja nicht wissen wie toll und schnell sein programm läuft, sondern wie viel zeit die berechnungen verbraten...
-
Aber eben die Berechnungen werden ja auch durch die Optimierung beeinflusst.
-
TactX schrieb:
Aber eben die Berechnungen werden ja auch durch die Optimierung beeinflusst.
aber eben deshalb muss man auch dafür sorgen, dass nix optimiert werden kann...
-
Also testen wir Berechnungen unter vollkommen unrealistischen Bedingungen um was rauszufinden? Die Vorteile der CPUs die ja teilweise nur in "realem" Code zum tragen kommen fliessen hier ja nicht ein. Ich sehe den Sinn einfach nicht

-
TactX schrieb:
Die Vorteile der CPUs die ja teilweise nur in "realem" Code zum tragen kommen fliessen hier ja nicht ein.
guck doch mal seine 'benchmark' funktion.
ein aggressiv optimierender compiler compiliert die zu *nichts*
es gibt da zwar 'realen' sourcecode, aber den kann er auch gleich in /* */ einpacken
-
net schrieb:
TactX schrieb:
Die Vorteile der CPUs die ja teilweise nur in "realem" Code zum tragen kommen fliessen hier ja nicht ein.
guck doch mal seine 'benchmark' funktion.
ein aggressiv optimierender compiler compiliert die zu *nichts*Klar. Ich meine ja nur, dass man sowas eh nur mit einem etwas besseren/realeren Test einigermassen aussagekräftig testen kann. Der Test wird ja nicht wirklich sinnvoller nur weil man das komplette Wegoptimieren unterbindet. Wenn eh nur die einzelnen Laufzeiten der ALU/FPU-Befehle interessieren, kann eh ins Manual schauen. Alle anderen Effekte (Pipelining, Caching, SIMD, whatever) scheinen euch ja nicht zu kehren.