Großen Speicher allocieren ? Größe des Heap's ?



  • Hallo zusammen,

    ich möchte eine Datei mit 20MB in meinen Programmspeicher einlesen.
    Diese Datei will ich in ein genauso großes byte (char) array laden.
    Nun gibt es anscheinend hier extrem viele Möglichkeiten seinen Heap zu sprengen 😞

    Nachdem ich nicht die geringste Ahnung habe, wollte ich zuerst:

    char myvariable[20480000]
    

    als globale Variable setzen, weil ich dachte das global der Heap nicht benutzt wird.

    Was soll ich sagen 😉 war ein Fehler ...

    Kann mir hier jemand sagen, wie es richtig geht ?
    Nochwas am Rande: Ich will das nicht mit Vectoren oder ähnlich machen, weil ich Wert auf einen schnellen Speicherzugriff lege. Also will ich sozusagen unmanaged fahren.

    Gruß
    TheNoName



  • std::vector ist schnell genug für dich.

    Ansonsten

    char * data = new char[20480000];
    


  • Du sprengst nicht den Heap, sondern den Stack.
    std::vector ist ca. so schnell, wie ein mit new angelegtes Array. Wenn du Größe im Konstruktor angibst, sollte es sogar identisch sein.

    Gruß
    Don06



  • Hi,

    ja, ich sprenge mit obiger Angabe den Stack 😞
    Aber mit:

    char * data = new char[20480000];
    

    sprenge ich doch auch ?
    Der Stack und der Heap haben doch nur bestimmte Größen ?

    Wenn ich mit 1MByte arbeite merke ich SEHR deutlich schon den Geschwindigkeitsunterschied zu vectoren !
    Also lasst bitte mal die vectoren aussen vor ...



  • Der Heap ist erst gesprengt, wenn du den kompletten Arbeitsspeicher beanspruchst, und das sollte nicht so schnell zu schaffen sein 😉



  • Verschweigst du uns etwa, dass du einen uralt PC mit nur 8MB Arbeitsspeicher hast? 😉
    Bei mir klappt auch noch das hier (hab 2GB Arbeitsspeicher):

    int main()
    {
    	char* one_gb_ram = new char[1024 * 1024 * 1024]; // 1073741824 Byte
    
    	delete[] one_gb_ram;
    
    	return 0;
    }
    

    Gruß
    Don06



  • thenoname schrieb:

    Wenn ich mit 1MByte arbeite merke ich SEHR deutlich schon den Geschwindigkeitsunterschied zu vectoren !
    Also lasst bitte mal die vectoren aussen vor ...

    Hast du das Megabyte im vornherein mir vector::reserve allokiert, oder pushst du einfach immer neue Objekte rein bis das MB voll ist?

    Bei letzterem muss der vector die Daten nämlich immer wieder um-kopieren um sich zu vergrößern, da ist das klar.
    Wenn du den Speicherplatz vorher reserviert hast, entfällt dieses zeitaufwändige Kopieren.



  • The-Kenny schrieb:

    thenoname schrieb:

    Wenn ich mit 1MByte arbeite merke ich SEHR deutlich schon den Geschwindigkeitsunterschied zu vectoren !
    Also lasst bitte mal die vectoren aussen vor ...

    Hast du das Megabyte im vornherein mir vector::reserve allokiert, oder pushst du einfach immer neue Objekte rein bis das MB voll ist?

    Bei letzterem muss der vector die Daten nämlich immer wieder um-kopieren um sich zu vergrößern, da ist das klar.
    Wenn du den Speicherplatz vorher reserviert hast, entfällt dieses zeitaufwändige Kopieren.

    nein, er mus snicht jedes mal umkopieren. nur wenn sich zusätzlicher speicher nicht direkt "im anschluss" reservieren läßt. aber worst case ist tatsächlich, dass er eine kopie des gesamten vectors instantiieren muss und wenn der zu kopierende vector bereits die hälfte des max speichers belegt, dann geht der schuss nach hinten los 😉 wie the-kenny schon richtig sagt: reserve sollte da abhilfe schafeen, wenn du weißt wie gross der speiche rungefähr werden soll



  • thenoname schrieb:

    Geschwindigkeitsunterschied zu vectoren !
    Also lasst bitte mal die vectoren aussen vor ...

    Wenn man die Arrays und die STL unter den gleichen Prämissen verwendet, ist der Geschwindigkeitsunterschied nahe bei 0.

    Thema 1: Allozierung & Freigabe
    Also was sind die Prämissen:
    a) Vector ist mit vorinitialisierten Elementen gefüllt
    b) Vector benutzt dynamische Speicherallozierung (Anlage & Löschen)

    Folgendes Programm dient nur dem Beispiel der Allozierung unter VC++ 2005 mit deaktivierter "Security" (er ist übervorsichtig):

    #define _SECURE_SCL 0
    
    #include <iostream>
    #include <vector>
    #include <boost/progress.hpp>
    
    void wait()
    {
        std::cin.clear();
        std::cin.ignore(std::cin.rdbuf()->in_avail());
        std::cin.get();
    }
    
    int main()
    {
    	for(int i=0; i<10; ++i)
    	{
    		boost::progress_timer t;
    		{
    			long* list = new long[100000000](); // () = Basisinititalisierung s.u.
    			delete[] list;
    		}
    	}
    	for(int i=0; i<10; ++i)
    	{
    		boost::progress_timer t;
    		{
    			std::vector<long> list(100000000);
    		}
    	}
    	wait();
    	return 0;
    }
    

    So... wenn man die Ergebnisse vergleicht kommt man etwa gleich weg. Wenn man aber auf eine Vorinitialisierung pfeift, macht das bei mir tatsächlich einiges aus (Nicht messbar gegenüber etwa 0,5 Sekunden).

    Thema 2: Durchiterieren auf verschiedene Art und Weise
    So, unabhängig von der Initialisierung will ich mal alle Werte einmal setzen (mit dem index)...

    a) Variante: Indexzugriff über for-Schleife

    // Nur main, ansonsten wie oben
    int main()
    {
    	std::vector<double> zeitmessungen(100);
    	for(int i=0; i<10; ++i)
    	{
    		long* list = new long[100000000]();
    		{
    			boost::progress_timer t;
    			for(int i=0; i<100000000; ++i)
    				list[i] = i;
    		}
    		delete[] list;
    	}
    	for(int i=0; i<10; ++i)
    	{
    		std::vector<long> list(100000000);
    		{
    			boost::progress_timer t;
    			for(int i=0; i<100000000; ++i)
    				list[i] = i;
    		}
    	}
    	wait();
    	return 0;
    }
    

    Ich komme in beiden Fällen auf die gleichen Werte (gegen 0,31 Sekunden)

    b) Variante: Vector durchiterieren und füllen

    // Nur Ausschnitt des entsprechenden Teilabschnittes
    	for(int i=0; i<10; ++i)
    	{
    		std::vector<long> list(100000000);
    		{
    			boost::progress_timer t;
    			for(std::vector<long>::iterator it = list.begin(), end = list.end(); it != end; ++it)
    				*it = i;
    		}
    	}
    

    Ebenso identisch...

    Mein Fazit
    1. Bei der Allozierung kann es ein unterschied machen, sofern man uninitialisierte Arrays mit (initialisierten) Vectoren vergleicht. Ansonsten ist der Unterschied nahe 0.

    2. Beim Zugriff nehmen sich beide Varianten nahezu 0

    Daraus folgere ich das ein oder mehrere der folgenden Dinge bei dir zutreffen:
    a) Du verwendest VC und kennst den Schalter _SECURE_SCL 0 nicht
    b) Du hast eine wirklich miese STL-Umsetzung
    c) Du machst den Fehler in jedem Schleifendurchgang end() neu zu bestimmen (it<list.end() ist tabu)
    d) Du verwendest ansonsten den Vector irgendwie falsch

    cu André



  • Naja, wenn der heap voll ist , wird evtl. auf den Virtuellen Arbeitspeicher gekapselt?


Anmelden zum Antworten