Laufzeitmessung
-
ok ich glaube ich verstehe was du meinst.
Wenn ich jetzt nach meiner Distanzberechnung eine weitere Schleife einbaue die mir beispielsweise die kürzeste Distanz zwischen 2 Raumkoordinaten berchnet dann sollte ich in dieser Schleife Performanceunterschiede zwischen 32bit und 64 bit erkennen. Dann würden ein Teil dieser Daten im Cache stehen weil ich bereits in der ersten Schleife darüber iteriert habe.
Da bei 64-Bit die Pointer aber doppelt so groß sind stehen im Cache bei 64-Bit nur halb so viel Information wie bei 32-Bit und somit müsste ich einen Performance unterschied in diesem Teil merken.Sehe ich das jetzt so richtig?
-
Nein!
Wenn du danach noch eine weitere Schleife einbaust, dann werden die Daten ja wieder in den Cache geladen, bearbeitet und dann wieder aus dem Cache entfernt, da dein Cache ganz bestimmt keine (50000000 * sizeof(Roboter)) Bytes umfaßt.
Außerdem arbeitest du ja auch mit Zeigern (Roboter*), d.h. diese Daten können theoretisch ja auch wild verstreut liegen (auch wenn sie höchstwahrscheinlich hintereinander im Speicher liegen werden, da du sie ja "am Stück" alloziert hast - aber in Realanwendungen können natürlich auch noch andere Blöcke dazwischenliegen).Wie dvid schon geschrieben hat, bringt der Cache nur dann Vorteile, wenn du mit denselben Daten sehr viele Berechnungen "am Stück" anstellst.
M.E. wirst du auf einem 64-bit-System mit 64-bit Code am schnellsten sein (und auf 32-bit-Systemen umgekehrt mit 32-bit Code).
-
Ich hab das doch so verstanden wenn ich Beispielsweise aus dem Hauptspeicher Daten hole(die <= Cachesize sind z.b. 1000 * sizeof(Roboter*)) und ich eine Operation auf diesen Daten ausführe(z.b. ich erhöhe jeden Eintrag um 1) dann liegen die Daten zwar alle im Cache es nützt mir aber nichts weil ich sie nicht öfter als einmal verwende!!!!
Wenn ich jetzt aber nach dieser Schleife eine weitere Einbaue in der ich die Daten sortiere, dann sollte mir der Cache aber schon einen Vorteil bringen weil die Daten ja bereits im Cache liegen wegen der vorherigen Schleife.
Dies sollte mir aber nur dann einen Leistungszuwachs bringen wenn die Daten wie gesagt nicht größer sind als Cachesize ist.Lieg ich noch immer falsch?
Wenn ja könnt ihr mir ein praxisnahes Beispiel nennen wo diese Thematik Anwendung findet damit ich das auch austesten kann?
Danke für die bisherigen Antworten
Lg
-
mulek schrieb:
Wenn ich jetzt aber nach dieser Schleife eine weitere Einbaue in der ich die Daten sortiere, dann sollte mir der Cache aber schon einen Vorteil bringen weil die Daten ja bereits im Cache liegen wegen der vorherigen Schleife.
Wie schon gesagt wurde nur dann, wenn die Daten, über die die schleifen laufen, weniger Platz beanspruchen als im cache vorhanden sind. Sagen wir mal du läufst über 20.000 Daten, es passen aber nur 10.000 in den Cache - dann werden nach der Hälfte des ersten Durchlaufs die ersten Daten aus dem Cache geworfen, und am Ende ist nur die "hintere" Hälfte der Daten im Cache. Bei der nächsten Schleife fängst du wieder von vorne an und musst wieder die ersten Daten neu in den Cache laden, hast also nichts gewonnen.
Ein Cache bringt dir nur dann was, wenn du
- auf eine gewisse Menge Daten mehrfach (= ziemlich oft) zugreifst und
- zwischen diesen Zugriffen nur auf so wenig andere Daten zugreifst dass die gecachten Daten nicht aus dem Cache geworfen werden.
-
ok, ja das ist mir jetzt bewusst.
Jetzt bin ich bei meinen Überlegungen auf eine andere Problematik gestoßen
Annahme:
Wieder mein Array mit 1000 Einträgen(Cache umfasst Bsp. 10000 Einträge)
Wenn ich jeden Inhalt des Arrays inkrementiere, wo wird dann das Ergebnis geschrieben, in den Cache da ja dort schon die Variable steht und nur noch die Daten geändert werden müssen, oder in den Hauptspeicher?

-
Wenns schon auf dem Cache ist dann wirds auf den Cache geschrieben. Wenn dann aber dein Array im Cache irgendwann ersetzt wird, muss das alles natürlich im Hauptspeicher wieder aktualisiert (zurückgeschrieben) werden.
Sag mal genauer was du vor hast, irgendwie hat das ganze wohl was mit 32 vs 64 Bit zu tun. Vielleicht kann man dir dann genaueres sagen, wo man nochwas rausholen kann.
gruß
-
Bin derzeit am Fertigstellen meienr Bak. Arbeit. Das Thema lautet Softwareentwicklung unter 64-Bit Systemen. Dabei geht es Hauptsächlich um den Unterschied zu 32-Bit, auf was man dabei achten muss, usw. Abschließend soll ich ein Beispiel programmieren für die Laufzeitmessung von 32-Bit und 64-Bit. Bei großen Datenmengen sinkt die Wirksamkeit der Caches bei 64-Bit(Pointer sind ja doppelt so lang und brauchen daher auch doppelt so viel Speicherplatz). Diese Problematik soll ich mit meinem Beispiel eben aufzeigen.
Also hätte ich mir folgendes gedacht:
vector<int*> als Datenstruktur
Operationen auf Vektorelemente ausführen(Alle Elemente passen gerade noch in den Cache unter 32-Bit).
Damit die Wirksamkeit der Caches hervorgeht alle diese Elemente danach sortieren und die Laufzeit messen(hier sollte ja nur mehr am Cache gearbeitet werden).Gleiche vorgehensweise bei 64-Bit. Problem ist jetzt dass die Vektorelemente nicht mehr alle in den Cache passen und somit die Performance unter 64-Bit sinkt da die Daten teilweise aus dem Hauptspeicher entnommen werden.
Gleichzeitig geht auch ein Vorteil von 64-Bit hervor:
Wenn alle Daten bei 32-Bit und 64-Bit in den Cache passen dann sollte bei 64-Bit eine Performancesteigerung (durch die zusätzlichen Register in einer 64-Bit Architektur) festgestellt werden.Diese Punkte sollte meine Performanceanalyse alle miteinbeziehen.
lg
-
Oh mann, das hört sich kompliziert an. Glaub eher nicht, dass ich Dir da helfen kann. Ich schreib mal einfach, was mir dazu spontan einfällt.
Bei großen Datenmengen sinkt die Wirksamkeit der Caches bei 64-Bit(Pointer sind ja doppelt so lang und brauchen daher auch doppelt so viel Speicherplatz). Diese Problematik soll ich mit meinem Beispiel eben aufzeigen.
Ist vielleicht nicht eher gemeint, dass wenn du in nem C Code einen plain int hast, der dann bei 64 Bit doppelt so groß ist. Mit Pointern hast du denk ich mal noch ganz andere Probleme, wie oben schon erwähnt.
vector<int*> als Datenstruktur
Operationen auf Vektorelemente ausführen(Alle Elemente passen gerade noch in den Cache unter 32-Bit).
Damit die Wirksamkeit der Caches hervorgeht alle diese Elemente danach sortieren und die Laufzeit messen(hier sollte ja nur mehr am Cache gearbeitet werden).Mach doch eher sowas.
int array[PASST_BEI_32_BIT_IN_CACHE];Dann ganz viel auf array rumrechnen. Dann den selben Code auf 64 Bit compilieren und Ergebnisse interpretieren. Ich wage es aber nicht eine Prognose abzugeben, dafür sind mir moderne CPUs zu komplex.
Gleichzeitig geht auch ein Vorteil von 64-Bit hervor:
Wenn alle Daten bei 32-Bit und 64-Bit in den Cache passen dann sollte bei 64-Bit eine Performancesteigerung (durch die zusätzlichen Register in einer 64-Bit Architektur) festgestellt werden.Das bezweifle ich stark, zumindest bei deinem Beispielcode. Du nutzt ja selbst im 32 Bit Code bei weitem nicht alle verfügbaren Register aus.
lg
-
#include <iostream> #include "StopWatch.h" using namespace std; #define CNT 25000000 int main(){ // Array das n-fache Cachegröße besitzt im Hauptspeicher anlegen int *NumberArray = new int[CNT]; int const OperationCounter = 1000; // Array mit 0 initialisieren for(int i=0;i<CNT;i++){ NumberArray[i] = 0; } //Startzeit double time = 0.0; stw::Start(); // Beliebige Operation einige "OperationCounter-fach" über Array laufen lassen for(int g=0;g<OperationCounter;g++){ for(int i=0;i<CNT;i++){ if(NumberArray[i] > 1000000){ NumberArray[i] = 0; } else{ NumberArray[i] = NumberArray[i]+1; } } } // Stopzeit time = stw::Stop(); int *NumberArray2 = new int[OperationCounter]; // Array mit 0 initialisieren for(int i=0;i<OperationCounter;i++){ NumberArray2[i] = 0; } //Startzeit double time2 = 0.0; stw::Start(); // Beliebige Operation sehr sehr oft über kleines Array laufen lassen(SpeedUp durch Cache) for(int i=0;i<CNT;i++){ for(int g=0;g<OperationCounter;g++){ if(NumberArray2[g] > 1000000){ NumberArray2[g] = 0; } else{ NumberArray2[g] = NumberArray2[g]+1; } } } // Stopzeit time2 = stw::Stop(); cout << "Laufzeit 1: " << time << endl; cout << "Laufzeit 2: " << time2 << endl; getchar(); return 0; } // CNT == 100000000 && OperationCounter == 1000 mit Speedoptimization // 32-Bit 64-Bit //Laufzeit 1: 181.491 //Laufzeit 2: 112.429 //Speedup: 100% - 61.8% = 38.2% // CNT == 50000000 && OperationCounter == 1000 mit Speedoptimization // 32-Bit 64-Bit //Laufzeit 1: 93.21 //Laufzeit 2: 56.363 //Speedup: 100% - 60.46% = 39.54% // CNT == 25000000 && OperationCounter == 1000 mit Speedoptimization // 32-Bit 64-Bit //Laufzeit 1: 46.597 46.644 //Laufzeit 2: 28.205 28.346 //Speedup: 100% - 60.5% = 39,5%so soweit kann ich den Performanceunterschied bei 32-Bit messen.
Jedoch kann ich den Unterschied zwischen 32-Bit und 64-Bit im Bezug auf den Cache nicht messen da ich dazu wissen müsste wieviele Daten ich maximal in den Cache reinbekomme. Und über dies kann ich keine Aussage treffen da ja da komplette Betriebsystem und andere Programme auch den Cache benutzen.
keine Ahnung wie ich da weitermachen soll!!!
-
...!
-
x64 sollte allein schon schneller sein da der Compiler mehr Register zur Verfügung hat und weniger mit dem Stack arbeiten muss.
-
ja das mit den registern weiß ich auch,
Aber ich will den FAll konstruieren wo 32-Bit in den Cache passt und 64-Bit nicht mehr ,und ich weiß nicht wie!!! Hierbei sollte sich ein erheblicher Laufzeitunterschied ergeben!!!!! Aber wie soll ich das implementiern?
Hier helfen mir die Register bei 64-Bit nicht mehr da ich auf einem viel langserem Speichermedium arbeite.Mir ist auch bewusst das wenn 32-Bit und 64-Bit nicht mehr in den Cache passt 64-Bit Code schneller sein sollte da dann dem Compiler wieder mehr register zur Verfügung gestellt bekommt.