Durchlaufzeit einer Schleife
-
SeppJ schrieb:
- Warum fstream, statt einem der ofstream, wenn du nur schreibst?
- Warum den Stream global? Bei lokalem Streamobjekt bräuchtest du auch den open/close Quatsch nicht.
- Warum new für Arrays? Das ist in C++ immer falsch. Nimm std::vector.
- Warum Variablen nicht direkt initialisieren? Besonders putzig sind die Zeilen 26,27.
- Galt für den Filestream besonders, aber gilt auch für deine anderen Variablen: Variablen so lokal wie möglich halten.
- Warum endl (was '\n' und flush() ist), wenn du doch nur '\n' meinst?
- Warum return 0 aus main?
- Nicht drüber nachgedacht, hab ich mal geändert.
- Weil der nur zum Debuggen gedacht ist, wird hinterher noch, im richtigen Projekt, eine eigene Klasse für geschrieben.
- Hatte in letzter Zeit nur in reinem C programmiert, und deswegen std::vector vergesssen, jedoch kann es sein dass ich aufgrund von Geschwindigkeit trotzdem ein Array verwenden muss.
- Wie gesagt, hab ich den Code recht schnell hingeklatscht, habe ich jetzt auch mal geändert.
- In dem Projekt stehen die Variablen in einer Klasse, wollte das ganze nur mögichst schnell abbilden und hab mir darüber keine Gedanken gemacht.
- Weil ich das Programm zu jeder zeit abbrechen möchte, ohne flush() ist nicht gesichert, dass die komplette Ausgabe in der Datei steht.
- Warum nicht?
Das Projekt läuft unter Windows, jedoch wollte ich an allen Stellen an denen es möglich ist es Systemunabhängig zu halten.
Weiterhin bin ich nicht an der Systemzeit interessiert, sondern an der reellen Zeit.Vielen dank an dieser Stelle für deine Hilfe :).
Gugelmoser schrieb:
Was ist mit
chronoaus C++11?Danke, habe
chronobisher noch nicht gekannt. Aber sehr schön, dass es mittlerweile einen standarisierten präzisen Timer gibt.Im folgenden nochmal der neue Code:
#include <iostream> #include <fstream> #include <stdlib.h> #include <chrono> #include <vector> using namespace std; int main(int argc, char *argv[]) { srand(time(NULL)); //Textdatei zum schreiben öffnen ofstream f ("TEST.txt"); //Schleifendurchläufe festlegen int anzahl = 2000*1000*40; //Puffer erstellen unsigned char *puffer = new unsigned char[anzahl]; vector<unsigned char> buffer(anzahl, 0); //Dauerschleife while(true) { //Startzeit holen auto t1 = chrono::high_resolution_clock::now(); //For-Schleife durchlaufen for(int i = 0; i < (anzahl); i+=4) { //Puffer füllen buffer.at(i) = 50; buffer.at(i+1) = 50; buffer.at(i+2) = 50; } //Endzeit holen auto t2 = chrono::high_resolution_clock::now(); //Durchlaufzeit in Millisekunden berechnen und in Datei screiben f << "Vector safe: " << chrono::duration_cast<chrono::milliseconds>(t2-t1).count() << "ms."<< "\n"; //Startzeit holen t1 = chrono::high_resolution_clock::now(); //For-Schleife durchlaufen for(int i = 0; i < (anzahl); i+=4) { //Puffer füllen buffer[i] = 50; buffer[i+1] = 50; buffer[i+2] = 50; } //Endzeit holen t2 = chrono::high_resolution_clock::now(); //Durchlaufzeit in Millisekunden berechnen und in Datei screiben f << "Vector: " << chrono::duration_cast<chrono::milliseconds>(t2-t1).count() << "ms."<< "\n"; //Startzeit holen t1 = chrono::high_resolution_clock::now(); //For-Schleife durchlaufen for(int i = 0; i < (anzahl); i+=4) { //Puffer füllen puffer[i] = 50; puffer[i+1] = 50; puffer[i+2] = 50; } //Endzeit holen t2 = chrono::high_resolution_clock::now(); //Durchlaufzeit in Millisekunden berechnen und in Datei screiben f << "Array: " << chrono::duration_cast<chrono::milliseconds>(t2-t1).count() << "ms."<< "\n" << endl; } }Und der Inhalt der TEST.txt:
Vector safe: 750ms. Vector: 156ms. Array: 93ms. Vector safe: 750ms. Vector: 140ms. Array: 78ms. Vector safe: 750ms. Vector: 156ms. Array: 78ms. Vector safe: 734ms. Vector: 156ms. Array: 78ms. Vector safe: 734ms. Vector: 156ms. Array: 78ms. Vector safe: 734ms. Vector: 156ms. Array: 78ms.
-
Du machst beim compilieren irgendwas massiv falsch. vector muss bei einem Releasebuild genau so schnell sein wie ein new-Array.
Ist er bei mir auch:
Vector safe: 56ms. Vector: 40ms. Array: 79ms. Vector safe: 55ms. Vector: 39ms. Array: 39ms. Vector safe: 54ms. Vector: 39ms. Array: 39ms. Vector safe: 55ms. Vector: 39ms. Array: 39ms. Vector safe: 55ms. Vector: 39ms. Array: 39ms.Der massive Zeitunterschied zwischen at und operator[] bei dir deutet ebenfalls auf Unsinn beim compilieren hin. So teuer ist ein Rangecheck nun auch nicht, wie du an meinen Zahlen siehst.
-
Das hätte ich auch erwartet.
Aber ideone sagt:Vector safe: 88ms. Vector: 86ms. Array: 85ms. Vector safe: 88ms. Vector: 86ms. Array: 38ms. Vector safe: 88ms. Vector: 86ms. Array: 39ms. Vector safe: 88ms. Vector: 86ms. Array: 38ms. Vector safe: 88ms. Vector: 86ms. Array: 38ms.Was mache ich jetzt falsch?
-
Caligulaminus schrieb:
Was mache ich jetzt falsch?
Du nimmst an, dass ideone optimieren würde. Probier mal bei dir zuhause.
-
Das nahm ich tatsächlich an.
Bei mir (MinGW 4.6.1) sind Vector und Array wieder gleichschnell - Danke.Gibt es einen Grund, warum ideone nicht optimiert?
-
Caligulaminus schrieb:
Gibt es einen Grund, warum ideone nicht optimiert?
Es ist eine Codeplattform, kein Rechenzentrum.
-
Bei mir ist es MinWG 4.6.2.
Vorher die Werte waren ohne jede Optimierung.Sobald ich den Compiler jedoch optimieren lasse ("-O1") komme ich auch auf vernünftige Ergebnisse.
Dankeschön an dieser Stelle nochmal.TEST.txt :
Vector safe: 30ms. Vector: 27ms. Array: 40ms. Vector safe: 32ms. Vector: 25ms. Array: 26ms. Vector safe: 29ms. Vector: 25ms. Array: 25ms. Vector safe: 30ms. Vector: 27ms. Array: 25ms. Vector safe: 31ms. Vector: 33ms. Array: 25ms. Vector safe: 30ms. Vector: 24ms. Array: 29ms. Vector safe: 30ms. Vector: 26ms. Array: 26ms.
-
Bei GCC basierten Compilern kannst du auch gefahrlos auf
O2gehen. SelbstO3macht in 99.9999% aller Fälle keine Probleme, bringt aber sehr viel. ErstOfastwird manchmal kritisch was die Programmkorrektheit angeht. Gut kommt auch die Optimierung zur Linkzeit:flto(ist aber ein bisschen frickelig zu benutzen). Und falls es nur für einen Rechner ist, Feintuning mitmarch.Du hattest noch ein paar Fragen weiter oben:
frmimue schrieb:
SeppJ schrieb:
- Warum return 0 aus main?
- Warum nicht?
Du zeigst damit, dass du nicht alle Feinheiten der Sprache beherrscht. Was anscheinend auch der Fall ist. Aber nun hast du eine weitere Feinheit gelernt: In main (und nur in main!) ist
return 0;implizit, sofern die Funktion nicht explizit anders verlassen wird.
-
SeppJ schrieb:
frmimue schrieb:
SeppJ schrieb:
Warum return 0 aus main?
Warum nicht?
Du zeigst damit, dass du nicht alle Feinheiten der Sprache beherrscht. Was anscheinend auch der Fall ist. Aber nun hast du eine weitere Feinheit gelernt: In main (und nur in main!) ist
return 0;implizit, sofern die Funktion nicht explizit anders verlassen wird.Ich sehe das genau andersherum als du. Wie viele Leute hab ich bei mir an der Uni schon gesehen, die einfach bei jeder Funktion einen
intals Rückgabetyp definieren, und nie etwas zurückgeben. Ich finde, jede Funktion, die nicht void als Rückgabetyp hat, hat eine return-Anweisung zu haben.
-
SeppJ schrieb:
frmimue schrieb:
SeppJ schrieb:
- Warum return 0 aus main?
- Warum nicht?
Du zeigst damit, dass du nicht alle Feinheiten der Sprache beherrscht. Was anscheinend auch der Fall ist. Aber nun hast du eine weitere Feinheit gelernt: In main (und nur in main!) ist
return 0;implizit, sofern die Funktion nicht explizit anders verlassen wird.Because we can? Wirklich? Das findest du ein gutes Argument?
Also ob
main()mit oder ohnereturn 0ist mMn. sowas von vollkommen egal. Ich würde es grundsätzlich eher hinschreiben, weil es mMn. kaum einen guten Grund gibt überhaupt zu wissen dassreturn 0implizit ist.
-
Ich hätte da noch ein kleines Proble:
Ist es normal, dass sich die Auflösung der chrono::high_resolution_clock verändert?
Gestern hatte ich noch eine Auflösung von 1ms, aber seid heute hatte ich nur noch 15ms Auflösung, gerade eben ist es plötzlich wieder auf 1ms gesprungen.#include <chrono> #include <iostream> using namespace std; int main() { auto t1 = chrono::high_resolution_clock::now(); auto t2 = chrono::high_resolution_clock::now(); while(t1==t2) t2 = chrono::high_resolution_clock::now(); cout << chrono::duration_cast<chrono::nanoseconds>(t2-t1).count() << " ns.\n"; cout << chrono::duration_cast<chrono::microseconds>(t2-t1).count() << " us.\n"; cout << chrono::duration_cast<chrono::milliseconds>(t2-t1).count() << " ms.\n"; cout << endl; }