Zu viel Speicher angefordert?



  • Hi,

    ich habe ein kleines Problem mit einem Programmierprojekt.

    Dabei werden ziemlich viele Memberklassen in einer Speicherklasse angelegt und schlussendlich ausgewertet. Es geht dabei um die Simulation von Würfelwürfen, die sich verschieden zusammensetzen können.

    Mir ist klar, dass das nicht unbedingt die klügste Art ist eine solche Aufgabe abzuarbeiten... Ich könnte natürlich würfeln, auswerten, wieder würfeln, alten Wurf überschreiben, auswerten... -> deutlich ressourcenschonender, es bietet sich aber für einige Dinge an die Datensätze vollständig bis zum Schluss vorliegen zu haben.

    Legt die Beispiele nicht auf die Goldwaage, ich bin relativ eingerostet was die Programmiererei angeht, habe keinerlei Zugriffskontrolle ect. eingebaut.

    class wurf {
    private:
    public:
        int ndice;
        int typedice;
    
        int *x;
        int *neyes;
    
        wurf();
        wurf(int);
        wurf(int,int);
        ~wurf();
    
        void Ausgabe();
    };
    typedef wurf *thr;
    
    class sim {
    private:
    public:
        int nthrows;
        int art;
        int anz;
        thr *nbase;
    
        sim();
        ~sim();
    };
    
    
    sim::sim(){
        this->nthrows = 1e7;
        this->anz = 10;
        this->art = 6;
    
        nbase = new thr[this->nthrows];
    
        for(int i = 0; i < this->nthrows; i++){
            nbase[i] = new wurf(anz,art);
        }
    }
    

    Soweit klappt das erstmal aber... ich bin bei sehr großen Datensätzen (nthrows > 1e7) auf ein Problem gestoßen
    und zwar sehe ich in meinem Konsolenfenster nach einer angemessenen Wartezeit folgende Ausgabe:

    terminate called after throwing an instance of "std::bad_alloc"
    what(): std::bad_alloc

    Dh, dass was bei der Speicherverwaltung nicht klappt, okay... aber ... sollte mir das noch mehr sagen? 10 000 000 Würfe klappt noch, 1e8 nicht mehr.



  • @Protagonist sagte in Zu viel Speicher angefordert?:

    dass was bei der Speicherverwaltung nicht klappt, okay... aber ... sollte mir das noch mehr sagen?

    Daß Dir der Speicher ausgeht. (bzw. zumindest der für ein "Array" erforderliche zusammenhängende Speicher)

    Würdest Du bitte ein vollständiges, kompilierbares Minimalbeispiel zeigen? Bitte nimm std::vector<> oder einen anderen Container statt new. Danke.

    @Protagonist sagte in Zu viel Speicher angefordert?:

    typedef wurf *thr;
    

    Man versteckt Pointer bitte nicht hinter typedefs. Ist bloß eine blöde Fehlerquelle und bringt nicht wirklich was. Apropos Pointer ... rohe besitzende Pointer sind out. ~> smartpointer, besser Container nehmen.



  • Der Speicherbedarf läßt sich ja einfach berechnen:

    // für die wurf-Objekte
    1e7 * sizeof(wurf) = 1e7 * (2 * sizeof(int) + 2 * sizeof(int*))
    // bei sizeof(int) = 4 und sizeof(int*) = 4 bzw. 8 (32 bzw. 64 Bit - je nach Kompilierung)
    = 1e7 * 16 // bzw. 24
    = 1.6e8 = 160.000.000‬ // bzw. = 2.4e8 = 240.000.000‬
    => 152MB // bzw. sogar 228MB
    

    Und bei einer Zehnerpotenz mehr dann ~1.5GB (bzw. 2.2 GB).

    Und zusätzlich noch für das Array dann

    1e7 * sizeof(wurf*)
    = 1e7 * 4 // bzw. 8
    = 4e7 // bzw. 8e7
    => 38 MB // bzw. 76MB
    

    Und auch hier bei einer Zehnerpotenz mehr ~380MB // bzw. 760MB (außerdem muß dieser Speicher dann am Stück verfügbar sein).

    Bei einem vector<wurf> würdest du dann zumindestens das Zeiger-Array einsparen (du solltest dann aber reserve(nthrows) aufrufen, um unnötiges [internes] Kopieren beim Einfügen (push_back()) zu vermeiden).



  • @Protagonist
    Ist deine Software eine 32 oder 64bit Anwendung?
    Das Problem wird sein, dass du Speicher am Stück anforderst. Auf einem 32bit System belegen 1e8 Pointer ca. 400MB, das könnte den Speichermanager überfordern. Du kannst die jetzt überlegen, ob wirklich alle im Speicher halten willst (dann musste dir eine andere Organisation der Daten überlegen. Würde ich dir auch so dringend empfehlen, denn es besteht keine Notwendigkeit, alle Würfe per new wurf(...) zu erzeugen. Schau dir unbedingt mal std::vector an!) oder ob du eine Möglichkeit findest, die Daten extern zu halten und bei Bedarf zu laden (zB. Memory Mapped Files, oder eine embedded Datenbank wie SQLite). Bei 1e8 Würfen hast du massenhaft Duplikate, vllt kannste dir für jedes Ergebnis einfach nur die Anzahl der Würfe merken (Bei einem W6 hast du 6 Möglichkeiten, statt sich jeden Wurf zu merken, reicht es da nicht aus sich zu merken, wie oft jede einzelne Zahl gewürfelt wurde?)
    Warum willst du den eigentlich alle Würfe im Speicher halten?



  • @Protagonist sagte in Zu viel Speicher angefordert?:

    int typedice;
    
    int *x;
    int *neyes;
    

    Was bedeuten diese Variablen?

    Und warum musst du so viele variable Würfelwürfe im Speicher halten?

    Besteht ein Wurf aus verschiedenen Würfeln oder sind das alles 6-seitige oder kann ein Wurf z.B. einen W6 und einen W12 enthalten?



  • @wob sagte in Zu viel Speicher angefordert?:

    Besteht ein Wurf aus verschiedenen Würfeln oder sind das alles 6-seitige oder kann ein Wurf z.B. einen W6 und einen W12 enthalten?

    Ah, ein Fachmann 😉



  • @DocShoe sagte in Zu viel Speicher angefordert?:

    @wob sagte in Zu viel Speicher angefordert?:

    Besteht ein Wurf aus verschiedenen Würfeln oder sind das alles 6-seitige oder kann ein Wurf z.B. einen W6 und einen W12 enthalten?

    Ah, ein Fachmann 😉

    Nein, bin kein Würfel-Fachmann, kenne aber ein paar Leute, die Rollenspiele machen. Ich bin eher für Brettspiele ohne oder mit nur wenig Würfeleinfluss (Lieblingsspiel aktuell: Istanbul)



  • @wob sagte in Zu viel Speicher angefordert?:

    Ich bin eher für Brettspiele ohne oder mit nur wenig Würfeleinfluss (Lieblingsspiel aktuell: Istanbul)

    Ah, ein Fachmann 😉



  • Tesserakte sind glaube ich besser zum Würfeln als herkömmliche Würfel, da sie glaube ich mehr Rotationsachsen aufweisen 🤪



  • @titan99_ sagte in Zu viel Speicher angefordert?:

    Rotationsachsen

    fail.



  • @Swordfish

    Punkte im Koordinatensystem:

    Würfel:

    (0, 0, 0)
    (1, 0, 0)
    (0, 1, 0)
    (1, 1, 0)
    (0, 0, 1)
    (1, 0, 1)
    (0, 1, 1)
    (1, 1, 1)

    Tesserakt:

    (0, 0, 0, 0)
    (1, 0, 0, 0)
    (0, 1, 0, 0)
    (1, 1, 0, 0)
    (0, 0, 1, 0)
    (1, 0, 1, 0)
    (0, 1, 1, 0)
    (1, 1, 1, 0)
    (0, 0, 0, 1)
    (1, 0, 0, 1)
    (0, 1, 0, 1)
    (1, 1, 0, 1)
    (0, 0, 1, 1)
    (1, 0, 1, 1)
    (0, 1, 1, 1)
    (1, 1, 1, 1)

    Also im Wikipedia-Artikel Eulersche_Winkel wird auch von Rotationsachsen geschrieben, die ja aber das Problem mit gimbal lock haben können.

    Wie lassen sich denn die drei starren Rotationsachsen in eine nicht unbedingt den Koordinatensystemachsen entsprechende Achse umwandeln?

    Edit: Auch z.B. einer rotierenden Welle kann noch weiter in einer weiteren Achse in Rotation versetzt werden...

    @Swordfish sagte in Zu viel Speicher angefordert?:

    @titan99_ sagte in Zu viel Speicher angefordert?:

    Rotationsachsen

    fail.

    Wieso 😐




Log in to reply