[Performance] inline-Inspector vs. friend Direktzugriff
-
Raptor schrieb:
Uebrigens:
const int* pX; //Das Object, auf das gezeigt wird, kann nicht veraendert werden int* pX const; //Der Pointer kann nicht mehr veraendert werden.
Fast.
const int* pX; //Das Object, auf das gezeigt wird, kann nicht veraendert werden int* const pX; //Der Pointer kann nicht mehr veraendert werden.
Sieht schon besser aus.
-
Meep Meep schrieb:
weils mich jetz doch mal genauer interessiert hab ich das mal ausgemessen. inwiefern das ein vernuenftiger test is, weiß ich nicht ;o)
hab mal folgendes getestet und mit rdtsc gemessen:
class klasse { private: int temp; int erg; public: void rechne1(void); void rechne2(void); }; void klasse::rechne1(void) { temp = 100000; erg = 0; for(int i = 0;i < temp;i++ erg += i; } void klasse::rechne2(void) { temp = 100000; int t_temp = temp; int t_erg = 0; for(int i = 0;i < t_temp;i++) t_erg += i; erg = t_erg; }
rechne1 brauchte bei mir ca. 660000 ticks und rechne2 ca. 220000 ticks. also grad mal ein drittel.
Meep Meep
So wie das da steht verwundert mich das doch erheblich. Hätte nicht gedacht, dass die Compiler da noch einen Unterschied lassen.
Dann hab ich das mal mit dem icc 8.1 getestet, und wenn man da die Optimierung einschaltet, erkennt der Compiler, dass in den Funktionen nichts getan wird und optimiert diese ganz weg.
-
womit der restliche sinn, meines eh schon sinnlfreien codes vollkommen entsorgt worden waere.
Meep Meep
-
volkard schrieb:
Meep Meep schrieb:
weils mich jetz doch mal genauer interessiert hab ich das mal ausgemessen. inwiefern das ein vernuenftiger test is, weiß ich nicht ;o)
hab mal folgendes getestet und mit rdtsc gemessen:ich hab deine test mal auch genommen.
hab die anzahl um faktor 100 vergrößert, damit ich feine sekundenanzahl bei mir kriege.Ist es überhaupt sinnvoll so große Zeiträume mit rdtsc zu messen? Da läuft doch soviel anderes Zeug, dass das Ergebnis stark verfälscht sein muss, oder nicht?
-
klar wird es verfaelscht.
aber ob ich jetz mit der systemzeit messe, oder mit rdtsc is ja egal. hab ja dann auch nur gerundete werte angegeben und nicht auf den tick genau. ich habs mit halt angewoeht mit rdtsc zu messenMeep Meep
-
Meep Meep schrieb:
klar wird es verfaelscht.
aber ob ich jetz mit der systemzeit messe, oder mit rdtsc is ja egal. hab ja dann auch nur gerundete werte angegeben und nicht auf den tick genau. ich habs mit halt angewoeht mit rdtsc zu messenMeep Meep
Ich meinte auch die ein-zwei Sekunden von volkard und nicht deine Paar Takte.
-
jo hab falsch gelesen.
womit und wie wuerdest du messen ?
Meep Meep
-
Meep Meep schrieb:
ich habs mit halt angewoeht mit rdtsc zu messen
ganz falscher ansatz.
du kannst mit rdtsc durchaus solche funktionen, die die chance haben, einmal durchzulaufen, ohne weggeschaltezt zu werden, also sagen wir mal mit laufzeiten im millisekundenbereich (sind ja noch 1000000 takte) auf 5 stellen genau ausmessen mit der einfachen schleifeint left=1000; time mintime=maxvalue<time>(); while(++left){ time t=measure(funktion); if(t<mintime){ mintime=t; left=1000; } }
das mache ich immer beim wpc, wenn speed das kriterium ist. und es funktioniert wunderbar.
-
koenntest du mir da mal erklaren was du da genau machst ? vorallem, was is maxvalue und die whileschleife wuerd mich interessieren
Meep Meep
-
Meep Meep schrieb:
jo hab falsch gelesen.
womit und wie wuerdest du messen ?
Meep Meep
Ich glaube im Bereich zwischen ganz kurz und lang gibt es keine gute Methode die CPU Zeit eines Prozesses zu messen. Für sehr kurze Bereiche kann man wohl rdtsc benutzen und für lange Bereiche times() oder getrusage(). Ich hab auch gelesen, dass der Kernel die CPU Zeit eines Prozesses nicht ganz korrekt mitführt.
Wenn es denn funktionieren würde kann man auch clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts) nehmen, aber mir ist das noch nicht untergekommen.
-
Meep Meep schrieb:
koenntest du mir da mal erklaren was du da genau machst ? vorallem, was is maxvalue und die whileschleife wuerd mich interessieren
Meep Meep
ganz einfach:
der kern ist die erkenntnis, daß die zu messende funktion nicht *schneller* als die echt zum berechnen benötigten takte sein kann, aber durch dazwischenfunkende andere prozesse beliebig langamer. also misst man einfach 1000000 aufrufe und nimmt den kleinsten messwert. irgendwann mal wird es der zufall so ergeben, daß die optimal kurze laufzeit, also die, wo zufällig kein anderer prozess dazwischenfunkte, gemessen wird.also kern ist, daß ich oft messe und das minimum nehme.
versuche zeigten, daß es saugeil ist, so lange zu messen, und immer das minimum sich zu merken, bis der messwert 1000-mal nacheinander nicht das minimum unterschreitet. ich liefere dazu keinen mathematischen beweis (der eh nur auf unsauberen annahmen über störende andere prozesse fußen könnte), sondern sage, daß ich damit sehr stabile messwerte erreiche. und glaibürdig werden die messwerte duch die stabilität.
-
Der inline-Instpector ist genau so schnell, wie der Direktzugriff ueber friend??
Donnerwetter!! Wenn man bedenkt, das es friend unter anderem deswegen gibt, wenn Klassen eng miteinander zusammenarbeiten so die Performance zu steigern.
Das haette ich jetzt nicht erwartet.Bin ganz begeistert von dem Feedback
-
Also irgendwie finde ich die simple Optimierung von Meep Meep den Hammer!!
Wie kann denn das sein, das der Compiler da nix machen kann?
Die Performance Unterschiede sind ja nun nich von Pappe.
-
Raptor schrieb:
Also irgendwie finde ich die simple Optimierung von Meep Meep den Hammer!!
Wie kann denn das sein, das der Compiler da nix machen kann?
Die Performance Unterschiede sind ja nun nich von Pappe.das hat was mit der geschichte von c++ zu tun.
es ist eine entscheidung "by design" wie microsaft sagen würde.nehmen wir ein beispiel, die sort-funktion. sie ist üblicherweise als introsort gebaut, also einem mischmach aus quicksort und heapsort. vielleicht mit einem terminierer für kleine bereiche garniert und einem nachfolgenden insertionsort, um den wieder auszubügeln.
ist das optimal? sicher nicht! ich lese vielleicht meistens dateien, die eine million adressen drin haben und sortiert sind und ändere pro sitzung nur 5 adressen. die einzusortierern mit introsort ist die hölle. schauen wir mal, ob quicksort oder selectionsort oder insertionsort (alle mot O(n^2) im zufälligren fall) nicht schneller sind. man findet eins mit O(n)! also O(5*n)==O(n). habe introsort für solche extremfälle nicht ausdiskutiert, aber selbst wenn es auch O(n) hätte, dann im faktiscchen vergleich sicher ne größenordnung mehr als direktes einsortieren mit insertionsort.
weil an sich zu 1000 aufgaben bestimmt 50 verschiedene sortierfunktionen optimal sind, und weil man in c++ das optimum sucht, wird es dem compiler wirklich verboten, zu erkennen, was der user denkt.
es wäre möglich, ein schleifenpaar, das ein quicksort ausführt, vom compiler automatisch erkennen zu lassen und durch introsort zu ersetzen. in 99.9% aller fälle wäre das sogar gut. aber nicht immer. extremprogrammierer wie ich würden sich voll angekackt fühlen, wenn sie den echt besten zur zeit bekannten algo für genau dieses problem gewählt hätten und der optimierer schmiert einen standard-algo drüber. in scriptsprachen darf er und saoll er das und das geht soweit bis java (ein lustiges zwischending).
das hat zur folge, daß um genau zu sein der user auch seinen compiler kennen soll und wissen soll, ob cachen was bringt. der user iszt ja der, der weißm welche daten vorliegen werden., wird die schleife meistens nur einmal durchlaufen und ist cachen vergäudete zeit? oder wird sie meistens oft durchlaufen und ist cachen toll? das weiß der compiler in c++ gar nicht.
in der lustigen sprache jave aber haben wir die rollen verdreht. da darf und kann der programmierer nicht so sachen entscheiden. da darf und kann der compiler entscheiden. er darf ordentliche datenfluss-analysen machen und in der tat bei einfachen problemen jeden c++-compiler wegputzen. während wir 10 jahre lang daran gerätselz haben, ob und wie man templates einseten kann, wie man in c++ echt außersprachliche dinge macht (statt eines besseren präprozessors), haben die in java sinnvolle sachen programmiert (also geld verdient) und ihren optimierer verbessert (ja, je einfacher die sprache, desto besser kann optimiert werden). wenn nicht bald was glaubwürdiges passiert, muss selbst ich wechseln. obwohl c++ genau die sprache ist, in der ich alles, was ich meine, einigermaßen elegant ausdrücken kann.
-
Der Compiler darf schon machen, was er will, um den Code schneller zu machen. Die einzige Bedingung ist, dass das nach außen sichtbare Ergebnis sich nicht durch die Optimierungen ändern darf.
Im vorliegenden Code erkennt der icc zum Beispiel, dass die Berechnungen in rechne1 und rechne2 überhaupt nicht verwendet werden und optimiert die beiden Aufrufe weg. Das ganze dauert dann nur noch 84 Takte in beiden Fällen.
Ich sehe nicht, warum der Compiler nicht das machen darf, was du für Java oder die Skriptsprachen beschrieben hast.
-
ganz wegmachen darf er. aber er darf im allgemeinen nicht einen sinnvollen algo durch einen anderen austauschen, obwohl er das gleiche ergebnis hat. weil man davon auszugehen hat, daß der programmierer sich bereits den angemessenen algo ausgeucht hat.
-
volkard schrieb:
ganz wegmachen darf er. aber er darf im allgemeinen nicht einen sinnvollen algo durch einen anderen austauschen, obwohl er das gleiche ergebnis hat. weil man davon auszugehen hat, daß der programmierer sich bereits den angemessenen algo ausgeucht hat.
Laut Standard darf der Compiler Algorithmen austauschen:
1.9.1:
The semantic descriptions in this International Standard define a parameterized nondeterministic abstract machine. This International Standard places no requirement on the structure of conforming implementations. In particular, they need not copy or emulate the structure of the abstract machine. Rather, conforming implementations are required to emulate (only) the observable behavior of the abstract machine as explained below.
1.9.5:
A conforming implementation executing a well-formed program shall produce the same observable behavior as one of the possible execution sequences of the corresponding instance of the abstract machine with the same program and the same input. However, if any such execution sequence contains an undefined operation, this International Standard places no requirement on the implementation executing that program with that input (not even with regard to operations preceding the first undefined operation).
1.9.6:
The observable behavior of the abstract machine is its sequence of reads and writes to volatile data and calls to library I/O functions.
-
Ponto schrieb:
Laut Standard darf der Compiler Algorithmen austauschen:
der standard erlaubt viel, wenn der tag lang ist. man würde so einen compiler augenblicks von der platte löschen.
-
Wenn man bedenkt, das es friend unter anderem deswegen gibt, wenn Klassen eng miteinander zusammenarbeiten so die Performance zu steigern.
Ne, das ist nicht der Sinn des Schlüsselwortes friend.