[Novize] Dynamic Memory Alloc ohne das User festlegt wie oft?
-
Wutz schrieb:
Oh man danke...wenn ich das dort so sehe sieht es alles so logisch aus...
Hier der Vorteil von realloc das er anstatt wie malloc ne Ganz andere Speicheradresse wählt - nimmt realloc ja die Erstaddresse von pNumber wieder auf um von dort aus den benötigten Speicher neu ranzuholen. Das war das Ding was mir die Ganze Zeit gefehlt hat.Ich dachte immer realloc könnte den neu alocalisierten Speicher nie über die Größe die Argument 1 hier pNumber schon hatte... d.h. er würde nicht über die 8 Byte eines doubles gehen.
Lag ich wohl falsch...
Danke für den Hinweis !
-
Falke88{tmp] schrieb:
- nimmt realloc ja die Erstaddresse von pNumber wieder auf um von dort aus den benötigten Speicher neu ranzuholen.
Nein, das ist bei realloc nicht garantiert.
realloc liefert (je nach Implementierung häufig) eben nicht immer den gleichen Zeiger zurück, sondern kann auch einen anderen Speicherbereich adressieren, wobei dann aber die im Originalspeicher liegenden Daten kopiert werden (in realloc).
Sicher kann man realloc-Aufrufe optimieren, auf gängigen Systemen sollte aber eher die Tastatur kaputtgehen, als dass der Speicher für neue sizeof(double)-Speicherbereiche ausgeht.
-
Ach falls die alte Addresse von pNumber nicht mehr verfügbar wäre (warum auch immer) würde realloc die Ganzen Daten mitnehmen auf ne neue Addresse??
Wollte nämlich gerade sagen falls realloc woanders anfängt würde pNumber[i] ja nichts mehr bringen da die Werte ja noch auf der alten Addresse liegen.
Interessant :o
-
Falke[tmp] schrieb:
Ach falls die alte Addresse von pNumber nicht mehr verfügbar wäre (warum auch immer) würde realloc die Ganzen Daten mitnehmen auf ne neue Addresse?
Wutz schrieb:
realloc liefert eben nicht immer den gleichen Zeiger zurück, sondern kann auch einen anderen Speicherbereich adressieren, wobei dann aber die im Originalspeicher liegenden Daten kopiert werden (in realloc).
-
ich habe es mal in einer Anwendung so gemacht, - erst mal 10K reserviert und
bei der Eingabe mitgezählt - wenn dann noch 1K übrig war (Länge der Eingabe stand fest), einfach wieder per realloc 10k angefordert usw.
Dann spart man sich das einzel-realloc und das ganze wird dann wohl auch performanter. (In diesem Fall ging es um die Anzeige von Buchungsdatenzeilen in einem Fenster aus ner Postgresql-DB, wobei die Anzahl der Buchungen vorher nicht feststand)
-
pferdefreund schrieb:
ich habe es mal in einer Anwendung so gemacht, - erst mal 10K reserviert und
bei der Eingabe mitgezählt - wenn dann noch 1K übrig war (Länge der Eingabe stand fest), einfach wieder per realloc 10k angefordert usw.
Dann spart man sich das einzel-realloc und das ganze wird dann wohl auch performanter. (In diesem Fall ging es um die Anzeige von Buchungsdatenzeilen in einem Fenster aus ner Postgresql-DB, wobei die Anzahl der Buchungen vorher nicht feststand)An sich guter Plan.
Aber man sollte sich anfgewöhnen, statt +=10000 gleich *=2 zu machen. Dadurch wird es nicht langsamer, wenn die Anzahl sehr sehr groß wird.
-
volkard schrieb:
Aber man sollte sich anfgewöhnen, statt +=10000 gleich *=2 zu machen. Dadurch wird es nicht langsamer, wenn die Anzahl sehr sehr groß wird.
wobei man das auch begrenzen muss. spaetestens wenn die groesse bei 1 GB ist sollte das naechste malloc nicht gleich 2 GB anfordern. Ich weis nur nicht wo man am besten die grenze zieht... Bei 10 MB? 100?
-
Real Locater schrieb:
volkard schrieb:
Aber man sollte sich anfgewöhnen, statt +=10000 gleich *=2 zu machen. Dadurch wird es nicht langsamer, wenn die Anzahl sehr sehr groß wird.
wobei man das auch begrenzen muss. spaetestens wenn die groesse bei 1 GB ist sollte das naechste malloc nicht gleich 2 GB anfordern. Ich weis nur nicht wo man am besten die grenze zieht... Bei 10 MB? 100?
Doch, einfach Durchziehen.
Lass uns mal Testhalber die Grenze bei 100M ziehen. Dann haste Vergrößerungen evtl mit Kopieren alle Elelente von 100M auf 200M, von 200M auf 300M...
100+200+300+400+500+600+700+800+900=4500 Kopierungen, also 4.5 pro Nutzbyte.
Und es wird um so schlimmer, je mehr Speicher belegt wird. Das wird ein Programm, das prinzipiell nur mit kleinen Datenmengen zurechtkommt, selbst wenn sich der User 16G Ram und 120G Swapspace gönnt.bei 10+20+30+...+990=49500(geschätzt), also 49.5 pro Nutzbyte.
Und es wird um so schlimmer, je mehr Speicher belegt wird.Bei 10+20+40+80+...+655360=1310710, also 1.3 pro Nutzbyte.
Und es wird nicht schlimmer, sondern bleibt zwischen 1 und 2.Kannst aber auch einen schwächeren Faktor nehmen, wie 1.5, solltest aber exponentiell bleiben.
-
hm, ok, hast mich überzeugt mit deinen Zahlen!
Ich kam auf den Trichter, weil ich mal bei so einer Funktion dann zum Testen eine 600 MB Datei reingeschoben habe und mir nicht gefiel, als dann malloc schiefging, weil es gleich 1 GB anfordern wollte.
Aber wenn man mit Speicherbereichen hantiert, die gut die Hälfte des Gesamtspeichers verbrauchen, sollte man da wohl eh anders rangehen.
-
Aber wenn man mit Speicherbereichen hantiert, die gut die Hälfte des Gesamtspeichers verbrauchen, sollte man da wohl eh anders rangehen.
Dumme Frage: Macht es perfomance-technisch etwas aus, wenn ich 200 MByte Chunks allokiere, als wenn ich diese mittels einer Liste allokieren würde?
-
In wie kleinen Teilen liegt denn deine Liste vor? Allgemein sind Listen im Vergleich zu anderen Datenstrukturen unglaublich lahm, außer bei ihrer einen Spezialität, dem Umhängen von Elementen. Je kleiner die Listenelemente, desto schlimmer.
-
Bitte ein Bit schrieb:
Aber wenn man mit Speicherbereichen hantiert, die gut die Hälfte des Gesamtspeichers verbrauchen, sollte man da wohl eh anders rangehen.
Dumme Frage: Macht es perfomance-technisch etwas aus, wenn ich 200 MByte Chunks allokiere, als wenn ich diese mittels einer Liste allokieren würde?
Chunks sind natürlich auch enorm gut. Die können auch nur 8k groß sein. Da wird der Index-Zugriff ganz ein Bißchen langsamer nur. Oder bei nur linearem Zugriff eine verkettet Liste von Chunks. Und dafür hat man gleich mal 0 Umkopierungen. Ist halt ein Bißchen mehr Programmieraufwand.
Aber ich würde mal nicht vernachlässigen, daß man immer mehr von 64-Bittern mit gigantischem Adressraum ausgehen kann. Ich habe neulich mit Feldern von 60G gearbeitet. Das ging noch recht schmerzfrei. Auslagerungsdatei groß genug machen und los geht's.
Eine normale verkettete Liste ohne Chunks ist bei kleinen Datenobjekten eher tödlich. Wenn ich bei 8Bytes Nutzdasten 24Bytes Verkettunsgkram- oder Speichermanagement-Kram habe, bräuchte ich dann 240G und so groß ich die SSD nicht und die Platte ist mal richtig lahm.
-
In wie kleinen Teilen liegt denn deine Liste vor?
Elementgröße liegt zwischen 20 und 100 Bytes, bei einer maximalen Größe des Array's von 100000 Elemente. Ok, hier macht eine Liste tatsächlich weniger Sinn.
Chunks sind natürlich auch enorm gut. Die können auch nur 8k groß sein.
Das verstehe ich nicht ganz. Unter Chunks meinte ich nur die Reservierung eines Speicherbereichs, in dem Elemente gespeichert werden (Array)
Was versteht du unter eine Chunk? Und warum können dies nur 8k groß werden?
-
Bitte ein Bit schrieb:
Was versteht du unter eine Chunk? Und warum können dies nur 8k groß werden?
In C++-Sprech meint volkard so etwas wie die deque. Also eine dynamische Datenstruktur, die intern eine Art Mischung aus Liste und Vektor ist, wobei die Daten in Blöcken vektorartig gespeichert werden, die wiederum listenartig verbunden sind. Mit "nur" meint er, dass sich das schon ab ein paar Kilobyte Blockgröße lohnt.
edit: "lohnt" mit Vorbehalt. Ein reiner Vektor wäre natürlich besser, aber wenn das nicht geht ist eine Liste nicht soooo schlimm, wenn sie bloß einigermaßen große Blöcke hat. Also nicht 20 Byte wie bei dir.
-
Bitte ein Bit schrieb:
Was versteht du unter eine Chunk? Und warum können dies nur 8k groß werden?
So ein Speicherbereich halt, den man schonmal reserviert und dann vollmacht.
Du hattest 200k-Chunks vorgeschlagen? Ist ok.
Aber 8k ist genauso gut. Rechnen wir mal 8 Bytes Overhead fürs Verknüpfen. Dann haben 0.1% Overhead. Deswegenreichen schon so kleine Chunks.
-
Falke88 schrieb:
Hey Leute,
Zerbreche mir hier gerade den Kopf an einer Aufgabe. Was ich hier machen möchte ist eine beliebige Anzahl von floating-point Werten vom User eingeben zu lassen. Der User kann soviele eingeben wie er möchte muss dafür auch vorher nicht angeben wieviel er eingeben wird.
Daher muss das Ganze mit "malloc" funktionieren.
Vielleicht kannst du die Werte sofort verrechnen. Dann musst du sie nicht alle speichern, sondern verrechnest jeden neuen Wert mit dem vorherigen Ergebnis. Es kommt darauf an, was du mit den Werten anstellen willst. Erzähl doch mal ...