Performance frage static /dynamic memory!?
-
@Th69 sagte in Performance frage static /dynamic memory!?:
Du müßtest auch das Allozieren und Löschen des Arrays in BM_dynamicMemorySet innerhalb der state-Schleife setzen, um einen Unterschied zu sehen (ich gehe davon aus, daß 100 die Anzahl der Schleifendurchgänge hier ist, oder?).
korrekt 100 tryes dann querschnitt (google benchmark)
-
@SoIntMan sagte in Performance frage static /dynamic memory!?:
habe gedacht, dass bei statischen speicher schon bei kompiletime die speicher stelle offsets gesetzt werrden , und bei dynamische zur laufzeut das erstgemacht wird..deswegn es einiges langsamer sein müsste...
Du scheinst die falsche Vorstellung zu haben, dass
static
irgendwie vorteilhaft wäre. Dabei ist das Gegenteil der Fall,static
ist der Tod aller Optimierungen. Beispielsweise darf hier der Compiler ja auf gar keinen Fall den Speicher vorab initialisieren, weil er sonst die Regeln für static-Variablen verletzen würde. Und auch sonst darf er absolut nix wegoptimieren, was irgendwie nach außen sichtbar wäre, was halt alles ist, was static ist. Bei rein internen Variablen könnte der Compiler pfuschen wie er will und sogar alles im Voraus berechnen. Daherstatic
nie zur Optimierung, sondern nur wenn technisch absolut notwendig (Also eigentlich nie).
-
@SeppJ sagte in Performance frage static /dynamic memory!?:
u scheinst die falsche Vorstellung zu haben, dass static irgendwie vorteilhaft wäre. Dabei ist das Gegenteil der Fall, static ist der Tod aller Optimierungen. Beispielsweise darf hier der Compiler ja auf gar keinen Fall den Speicher vorab initialisieren, weil er sonst die Regeln für static-Variablen verletzen würde. Und auch sonst darf er absolut nix wegoptimieren, was irgendwie nach außen sichtbar wäre, was halt alles ist, was static ist. Bei rein internen Variablen könnte der Compiler pfuschen wie er will und sogar alles im Voraus berechnen. Daher static nie zur Optimierung, sondern nur wenn technisch absolut notwendig (Also eigentlich nie).
ja das "static" keyword hatte ich jetzt hier nicht im blick, es ging mir um die primär darum dass ich dachte, dass vorab definierte speicherblöcke und nicht zur laufzeut erzeugte speicherblöcke in einen anderen speicher segement gelegt werden, deren zugriff viel effinzienter sein soll!?
hab mal das "static" entfertn, und den speicher block global angelegt, leider sehe ich da auch keine verbesserung!
const int SIZE = 1000000; typedef struct { int a; double b; } xx; xx arr[SIZE]; static void BM_staticMemorySet(benchmark::State& state) { for (auto _ : state) { for (int i = 0; i < SIZE; ++i) { arr[i]= { i,(double)i * 2 }; } benchmark::DoNotOptimize(arr); } } BENCHMARK(BM_staticMemorySet); static void BM_dynamicMemorySet(benchmark::State& state) { xx* arr = new xx[SIZE]; for (auto _ : state) { for (int i = 0; i < SIZE; ++i) { arr[i] = { i,(double)i * 2 }; } benchmark::DoNotOptimize(arr); } delete[] arr; } BENCHMARK(BM_dynamicMemorySet);
-
Wie kommst du darauf, daß der Speicherzugriff effizienter sein soll? Beides sind Speicherblöcke im Hauptspeicher (RAM).
Nur das Verwenden von lokalen Variablen (bei höchstens der max. Registerbreite) kann der Compiler so optimieren, daß nur interne CPU-Register benutzt werden, und damit schneller als ein Speicherzugriff ist.Außerdem könntest du ja einfach den Schleifen-Code in eine eigene Funktion auslagern:
void InitArray(xx *arr) { for (auto _ : state) { for (int i = 0; i < SIZE; ++i) { arr[i] = { i,(double)i * 2 }; } benchmark::DoNotOptimize(arr); } }
Und jeweils mit
InitArray(xx)
aufrufen.
Da gibt es (auch) keinen Unterschied im Laufzeitverhalten.
-
@SoIntMan sagte in Performance frage static /dynamic memory!?:
ja das "static" keyword hatte ich jetzt hier nicht im blick, es ging mir um die primär darum dass ich dachte, dass vorab definierte speicherblöcke und nicht zur laufzeut erzeugte speicherblöcke in einen anderen speicher segement gelegt werden, deren zugriff viel effinzienter sein soll!?
Ich erkläre dir, warum
static
böse für Optimierungen ist, weil es global sichtbar ist, und du probierst als nächstes echten globalen Speicher aus und wunderst dich über mangelnde Optimierung
-
@SoIntMan sagte in Performance frage static /dynamic memory!?:
hab mal das "static" entfertn, und den speicher block global angelegt, leider sehe ich da auch keine verbesserung!
Woher sollte auch eine Verbesserung kommen?
Anders sieht die Sache zwischen
std::list
vsstd::array
aus.
-
@SeppJ sagte in Performance frage static /dynamic memory!?:
@SoIntMan sagte in Performance frage static /dynamic memory!?:
ja das "static" keyword hatte ich jetzt hier nicht im blick, es ging mir um die primär darum dass ich dachte, dass vorab definierte speicherblöcke und nicht zur laufzeut erzeugte speicherblöcke in einen anderen speicher segement gelegt werden, deren zugriff viel effinzienter sein soll!?
Ich erkläre dir, warum
static
böse für Optimierungen ist, weil es global sichtbar ist, und du probierst als nächstes echten globalen Speicher aus und wunderst dich über mangelnde Optimierungok. gut dann habe ich wohl gar nichts verstanden. Aber wie müssten den die implementierung aussehen damit ich Signifikate unterschied sehe?
@Quiche-Lorraine sagte in Performance frage static /dynamic memory!?:
Woher sollte auch eine Verbesserung kommen?
Anders sieht die Sache zwischen std::list vs std::array aus.is das nicht das gleich wie arr[size] and arr = new (size)
-
@SoIntMan sagte in Performance frage static /dynamic memory!?:
ok. gut dann habe ich wohl gar nichts verstanden. Aber wie müssten den die implementierung aussehen damit ich Signifikate unterschied sehe?
Hier eigentlich gar nix, denn das was passiert ist nicht spannend genug, um Optimierungspotential zu haben.
Meine Bemerkung war eher allgemein, nicht auf diesen speziellen Fall. Du scheinst irgendetwas über static, new & Co. aufgeschnappt zu haben, das nicht stimmt. Das wollte ich korrigieren.
is das nicht das gleich wie arr[size] and arr = new (size)
Du verwechselt list mit vector.
-
@SeppJ sagte in Performance frage static /dynamic memory!?:
Meine Bemerkung war eher allgemein, nicht auf diesen speziellen Fall. Du scheinst irgendetwas über static, new & Co. aufgeschnappt zu haben
Ja das genau habe ausgeschnappt (CoPilot) hier ein abschnitt:
Access Speed:
Static Memory: Generally faster due to fixed addresses and better cache utilization. The access patterns are predictable, which helps in optimizing cache usage.
Dynamic Memory: Slower due to potential cache misses and the overhead of pointer dereferencing. The access patterns can be less predictable, leading to more cache misses.
-
@SoIntMan sagte in Performance frage static /dynamic memory!?:
CoPilot
Kein Kommentar...
Das "static" da hat nix mit
static
zu tun.Wildes Herumspringen im Speicher ist es, was Cachemisses erzeugt. Das ist aber keine Eigenschaft von statischem oder dynamischem Speicher, sondern von dem, was man damit macht. Mit dynamischen Speicher ist es halt einfacher, komplexe Datenstrukturen aufzubauen. Die können dann langsamer sein bei schödem iterativen Zugriff, aber das ist nix negatives, denn man hat die Struktur ja gebaut, damit sie spezielle andere Eigenschaften hat, die man braucht. Siehe
list
,vector
,array
. List ist dynamisch und kann viel mehr als die beiden anderen ist aber viel langsamer bei iterativem Zugriff, weil man dann wild im Speicher herumspringt. vector ist dynamisch, kann aber auch nicht wirklich mehr als array (außer dynamisch zu sein) und ist entsprechend bei iterativem Zugriff genauso schnell. Array ist statisch, aber wenn du dumm drin herumspringst, statt von vorne nach hinten durchuzugehen, wäre es genau so langsam wie eine Liste.
-
@SeppJ sagte in Performance frage static /dynamic memory!?:
Das "static" da hat nix mit static zu tun.
Wildes Herumspringen im Speicher ist es, was Cachemisses erzeugt. Das ist aber keine Eigenschaft von statischem oder dynamischem Speicher, sondern von dem, was man damit macht. Mit dynamischen Speicher ist es halt einfacher, komplexe Datenstrukturen aufzubauen. Die können dann langsamer sein bei schödem iterativen Zugriff, aber das ist nix negatives, denn man hat die Struktur ja gebaut, damit sie spezielle andere Eigenschaften hat, die man braucht. Siehe list, vector, array. List ist dynamisch und kann viel mehr als die beiden anderen ist aber viel langsamer bei iterativem Zugriff, weil man dann wild im Speicher herumspringt. vector ist dynamisch, kann aber auch nicht wirklich mehr als array (außer dynamisch zu sein) und ist entsprechend bei iterativem Zugriff genauso schnell. Array ist statisch, aber wenn du dumm drin herumspringst, statt von vorne nach hinten durchuzugehen, wäre es genau so langsam wie eine Liste.ok wenn kurz, solange ich den Speicher lineare durchiteriere (loop) den ich "dynamisch" allokiert habe macht es kein unterschied zu statischem Speicher? (allokiert mallock immer einen "ganzen" block). Wenn ich aber sporadisch hin und her springe bin ich bei statische schneller...?
std::list ist ja als linked list implementiert oder? da kann ja jedes element ganz woanders liegen?
-
@SoIntMan sagte in Performance frage static /dynamic memory!?:
ok wenn kurz, solange ich den Speicher lineare durchiteriere (loop) den ich "dynamisch" allokiert habe macht es kein unterschied zu statischem Speicher?
Ja.
(allokiert mallock immer einen "ganzen" block).
Ja.
Wenn ich aber sporadisch hin und her springe bin ich bei statische schneller...?
Nein. Außer eventuell doch ja, aber dann durch so komische Effekte, wie dass du bei statischer Allokation größenmäßig sehr beschränkt bist, so dass sowieso alles im Cache liegt. Aber das ist weiterhin keine Eigenschaft des statischen Speichers an sich, sondern davon, dass man damit weniger machen kann, was langsam sein könnte. Würdest du in einem kleinen Block dynamischen Speichers gelegentlich hin und her springen, wäre das genauso schnell wie in einem kleinen Block statischen Speicher gelegentlich hin und her zu springen. Wenn du die Größenlimits deines statischen Speichers ausschaltest und in einem riesigen Block gelegentlich hin und her springen, wäre es genauso langsam wie in einem riesigen Block dynamischen Speichers hin und her zu springen. Wie jetzt schon oft gesagt, gibt es keinen prinzipiellen technischen Unterschied zwischen statischen und dynamischen Speicher, sondern alle Unterschiede kommen daher, was man damit macht (Es gibt noch einen Unterschied darin, wie aufwändig die Anforderung eines neuen Blocks ist, aber das lassen wir mal außen vor, weil es hier um Unterschiede bei der Nutzung geht).
std::list ist ja als linked list implementiert oder?
Ja.
da kann ja jedes element ganz woanders liegen?
Ja.
-
@SeppJ sagte in Performance frage static /dynamic memory!?:
Wie jetzt schon oft gesagt, gibt es keinen prinzipiellen technischen Unterschied zwischen statischen und dynamischen Speicher, sondern alle Unterschiede kommen daher, was man damit macht (Es gibt noch einen Unterschied darin, wie aufwändig die Anforderung eines neuen Blocks ist, aber das lassen wir mal außen vor, weil es hier um Unterschiede bei der Nutzung geht).
Super Danke für deine Ausführungen, hat mir geholfen es zu verstehen. In meinen Fall ist das dann super.. da ich meinen speicher nur "einmal" bei initalisieren dynamisch allokcieren und nur noch verwende. Hätte eben gedacht wenn ich der speicher statisch ist, dass ich performance vorteile habe. Und vom caching her,passt es auch, weil ich auch keine wilden array sprünge mache:)
-
Ich hoffe doch, dass das kein reales Beispiel war? Benutz in echtem Code bloß kein new/delete (außer du baust eigene Allokatoren o.Ä.)! Rule of 0!
-
@SeppJ sagte in Performance frage static /dynamic memory!?:
Ich hoffe doch, dass das kein reales Beispiel war? Benutz in echtem Code bloß kein new/delete (außer du baust eigene Allokatoren o.Ä.)! Rule of 0!
Nein war nur dummy code... aber sorry das verstehe ich jetzt nicht in c++ new/delete c malloc/free? oder wie meinst du das?
im produktiv code c muss ich malloc/Free nehmen und .. in C++ smart ptr etc. also nicht nativ new/Delete;)
-
@SoIntMan sagte in Performance frage static /dynamic memory!?:
@SeppJ sagte in Performance frage static /dynamic memory!?:
Ich hoffe doch, dass das kein reales Beispiel war? Benutz in echtem Code bloß kein new/delete (außer du baust eigene Allokatoren o.Ä.)! Rule of 0!
Nein war nur dummy code... aber sorry das verstehe ich jetzt nicht in c++ new/delete c malloc/free? oder wie meinst du das?
Mit C++11 wurden smart pointer eingeführt, sodass man eigentlich kein
new
unddelete
mehr braucht.
-
Was hast du denn mit Smart Pointern vor, was mit den fertigen Containern nicht besser geht?
-
@SeppJ sagte in Performance frage static /dynamic memory!?:
Was hast du denn mit Smart Pointern vor, was mit den fertigen Containern nicht besser geht?
doch geht bestimmt besser.. habe vll. die falsche foren seite.. bin in der C welt unterwegs...;)
-
@SoIntMan sagte in Performance frage static /dynamic memory!?:
im produktiv code c muss ich malloc/Free nehmen und .. in C++ smart ptr etc. also nicht nativ new/Delete;)
Manuelle Speicherverwaltung ist generell anfällig für Fehler. Ein klassischer Fall, eine etwas größere Funktion nutzt diverse allokierte Sachen und innerhalb der Funktion muss an diversen Stellen die Funktion beendet werden.
Überall wo nun die Funktion sich beendet, müssen alle allokierten Ressourcen freigegeben werden. Wie macht man dies am besten und möglichst fehlerfrei?
In so manchem alten DirectX Code von Microsoft sieht man da ein
goto
, was für C ok ist. In C++ nutzt man dagegen RAII.Nehmen wir mal z.B. die Klasse
std::string
. Diese allokiert intern einen Speicher, zur Speicherung des String. Füge ich Zeichen hinzu, so stellt die Klasse sicher dass der String vollständig gespeichert wird. Notfalls allokiert die Klasse einen größeren Speicher, kopiert die alten Daten rein, fügt die Zeichen hinzu und löscht den alten Speicher. Erreicht die Instanz das Lebensende, so löscht der Destruktor der Klasse automatisch die allokierten Ressourcen.Dadurch vereinfacht sich das Beenden einer Funktion erheblich, da automatisch die Ressourcen freigegeben werden und dadurch Speicherlöcher nicht mehr vorkommen.
-
@SoIntMan sagte in Performance frage static /dynamic memory!?:
bin in der C welt unterwegs...;)
Das ging aus deiner Frage im C++-Forum mit C++-Code nicht so ganz klar hervor