Speicherplatzverschwendung/-verbrauch?
-
also wie gesagt die Zeiger sind nur NULL-Pointer zeigen also auf keine Objekte, der Speicherplatz für die Zeiger wird aber mit malloc() allokiert. das hab ich deshalb gemacht, weil es da die realloc() funktion gibt um das array nachträglich vergrößern zu können, gibts ja für new() nicht soweit ich weiß.
und da mir hier im forum mal gesagt wurde, dass es nicht festgelegt ist, das new und malloc im gleichen speicher (adressraum) arbeiten, kann man wohl auf new[]-zeiger kein realloc anwenden. was ich also habe ist sowas wiefloat ***a; a = (float***) malloc (100 * sizeof(float**)); for(int i = 0; i < 100; i++) { a[i] = (float**) malloc (100000 * sizeof(float*)); for(int j = 0; j < 100000; j++) a[i][j] = 0; };und dieses feld verbraucht an die 210MB, obwohl eigentlich nur 40MB zu veranschlagen wären, plus den programm-offset
-
ich seh gerade so wie es oben steht ist es noch ok, aber folgendes liefert mir sogar über 500MB
float ***a; a = (float***) malloc (100 * sizeof(float**)); for(int i = 0; i < nscc; i++) { a[i] = (float**) malloc (100000 * sizeof(float*)); for(int j = 0; j < n; j++) a[i][j] = (float*) malloc (sizeof(float)); };obwohl es eigentlich nur 80MB veranschlagen dürfte
-
realloc heißt in C++ "std::vector<T>::resize"
außerdem ist es logisch, dass dein Programm RAM und CPU frisst wie Sau, wenn du für jedes float eine Allokation ausführst (welche selber Zeit und Speicher-overhead kostet). Müsste in diesem (und jedem halbwegs populärem C++ -- ) Forum schon x-mal durchgekaut worden sein.
-
Du hast ein overhead pro Allokation:
- Verwaltung des Heaps (variiert, kann im Debug-Build höher sein)
- Alignment: malloc garantiert, daß der zurückgegebene Zeiger korrektes alignment für alle Typen hat. Das sollten unter x86 16 Byte für die SSE-Typen sein (mindestebns 8 für die dem compiler bekannten)
- Unter Debug-Builds kommen noch Guard Bytes hinzuSo oder so ist es nicht sinnvoll, für jeden einzelnen float eine Allokation durchzuführen. Wieso machst du das?
-
das mit dem float war nur stellvertretend eigentlich ist es ein beliebiger typ.
gut dann komme ich wohl nicht drumherum es noch genauer zu schildern.template<class t> class carray { long l; t **_data; //t = (t**) malloc (l * sizeof(t*)); //t[i] = (t*) malloc (sizeof(t)); };was ich nun habe ist etwas folgender art
carray<carray<ttyp> a;das beispiel oben ist quasi für ttyp = float
die doppelten zeiger haben den hintergrund, dass wenn ich zwei elemente im array vertauschen muss ich dann nur die zwei zeiger umhängen muss und mir somit das umkopieren eines evtl großen objektes sparen kann.
ich dachte mir, dass das bei großen objekten relevant sein könnte.obiges beispiel hätte a die dimension 100x100000, wenn ich dann also zwei 100000er arrays vertauschen will müsste ich normal alles in eine dummyvariable kopieren usw. kennt man ja, so muss ich nur die zwei zeiger vertauschen.
-
achso, im Debugmodus hab ich ca 500MB und im Releasemodus ca 200MB Speicherverbrauch
-
FreakyBKA schrieb:
achso, im Debugmodus hab ich ca 500MB und im Releasemodus ca 200MB Speicherverbrauch
Auch das ist logisch, denn im Debug-Modus wird noch gespeichert wer die Allokation durchgeführthat um Leaks leicht entdecken zu können.
-
die doppelten zeiger haben den hintergrund, dass wenn ich zwei elemente im array vertauschen muss ich dann nur die zwei zeiger umhängen muss und mir somit das umkopieren eines evtl großen objektes sparen kann.
Klingt sinnvoll, aber damit bestrafst du viele Instanzen kleiner Typen ziemlich heftig.
Gibt es einen Grund, daß du kein C++ verwendest?
Du kämst wahrscheinlich insgesamt besser, wenn du größere Objekte in einen smart pointer stopfst, oder zumindest eine "effiziente, non-throwing" swap-Implementaiton forderst.
Alternativ kannst du kleine Objekte auch auf einem separaten heap anlegen. Wenn du den Graphen immer nur im ganzen wieder freigibst, würde ein non-freeing heap praktisch kein Overhead bedeuten.
-
Klingt sinnvoll, aber damit bestrafst du viele Instanzen kleiner Typen ziemlich heftig.
richtig mir ist aber nichts eingefallen was ich sonst hätte machen können. bin für andere vorschläge sehr dankbar.
Gibt es einen Grund, daß du kein C++ verwendest?
was genau meinst du damit?
Du kämst wahrscheinlich insgesamt besser, wenn du größere Objekte in einen smart pointer stopfst, oder zumindest eine "effiziente, non-throwing" swap-Implementaiton forderst.
was sind smart-pointer? meinst du damit, dass ich dann als template-typ einen zeiger des template-typs verwende also:
//statt carray<tobject> //lieber carray<tobject*>Alternativ kannst du kleine Objekte auch auf einem separaten heap anlegen. Wenn du den Graphen immer nur im ganzen wieder freigibst, würde ein non-freeing heap praktisch kein Overhead bedeuten.
was ist ein non-freeing heap?
-
peterchen schrieb:
- Alignment: malloc garantiert, daß der zurückgegebene Zeiger korrektes alignment für alle Typen hat. Das sollten unter x86 16 Byte für die SSE-Typen sein (mindestebns 8 für die dem compiler bekannten)
Für alle Typen die reinpassen

Also wenn man 1 Byte (=char) alloziert, dann muss die Adresse nicht geeignet sein, um nen int abzulegen (angenommen int hat > 1 Byte, was in C++ ja nicht sein muss).Heisst konkret: wenn der Allocator es kann (und es gibt einige die das können), dann kann man schon bei 1 Mio. Anforderungen von jeweils 1 Byte, mit einem Speicherverbrauch von 1 MB auskommen.