Gute C ++ - Array-Klasse für den schnellen und speichereffizienten Umgang mit großen Datenfeldern?

7

Im Anschluss an eine vorherige Frage zu Beschränkungen der Heap-Nutzung Ich bin auf der Suche nach einer guten Standard-C ++ - Klasse für den Umgang mit großen Datenfeldern, die sowohl effizient als auch effizient ist. Ich hatte das Array mit einem einzigen malloc / HealAlloc zugewiesen, aber nach mehreren Versuchen mit verschiedenen Aufrufen, fallen immer wieder mit Heap-Fragmentierung. Die Schlussfolgerung, zu der ich gekommen bin, abgesehen von der Portierung auf 64 Bit, ist die Verwendung eines Mechanismus, der es mir ermöglicht, ein großes Array zu haben, das mehrere kleinere Speicherfragmente überspannt. Ich möchte keine Zuweisung pro Element, da dies sehr ineffizient ist. Daher ist es geplant, eine Klasse zu schreiben, die den Operator [] überschreibt und ein geeignetes Element basierend auf dem Index auswählt. Gibt es schon eine anständige Klasse, um das zu tun, oder sollte ich lieber meine eigene machen?

Nach meinem Verständnis und einigen Googeln sollte ein 32-Bit-Windows-Prozess theoretisch in der Lage sein, sich zu befassen zu 2GB. Nun, vorausgesetzt, ich habe 2 GB installiert, und verschiedene andere Prozesse und Dienste sind etwa 400 MB, wie viel nutzbarer Speicher, denke ich, kann mein Programm vernünftigerweise erwarten, aus dem Heap zu bekommen?

Ich verwende derzeit verschiedene Varianten von Visual C ++.

Bearbeiten Wie in Poitas Post beschrieben, habe ich eine std :: deque mit dem folgenden Test auf VS2008 versucht;

%Vor%

Der Gesamtspeicher für die oben genannten Daten kommt bei 608 MB heraus, sollte ich gerade malloc oder HeapAlloc verwenden und nimmt & lt; 1 Sekunde. Die Deque-Größe nahm ursprünglich 950MB und begann dann langsam zurückzufallen. 15 Minuten später endete dequeTest () mit nur 6 MB Speicher für den Prozess, der wahrscheinlich mehr mit den Laufzeiten zu tun hatte. Ich habe auch versucht, die Deque mit verschiedenen Push-Optionen zu füllen, aber die Leistung war so schlecht, ich musste früh ausbrechen. Ich könnte möglicherweise einen besseren Allokator als die defualt bieten, um eine viel bessere Antwort zu erhalten, aber auf den ersten Blick ist deque nicht die Klasse für diesen Job. Beachten Sie, dass sich dies auch auf die MS VS2008-Implementierung von deque beziehen könnte, da es in dieser Klasse sehr viele zu geben scheint, die hinsichtlich der Leistung sehr implementierungsabhängig sind.

Zeit, meine eigene große Array-Klasse zu schreiben, denke ich.

Second Edit: Die Zuweisung kleinerer Beträge führte sofort zu 1,875 GB mit dem folgenden Befehl;

%Vor%

Final edit Ich habe mich entschieden, Poitas Post und die verschiedenen Kommentare zu akzeptieren, nicht weil ich die Deque-Klasse direkt verwenden werde, sondern mehr für das Array als Kartenspiel die Kommentare, die folgten. Dies sollte einfach zu implementieren sein mit O (1) Zufallselementzugriff basierend auf einer festen Anzahl von Elementen pro Block, was ich brauche. Danke an alle für das Feedback!

    
Shane MacLaughlin 18.03.2010, 19:54
quelle

4 Antworten

11

Haben Sie versucht, ein std::deque zu verwenden? Im Gegensatz zu std::vector , das eine große Heap-Zuweisung verwendet, wird deque normalerweise in kleinen Blöcken zugewiesen, bietet aber weiterhin eine amortisierte konstante Zeitindizierung über operator[] .

    
Peter Alexander 18.03.2010, 20:00
quelle
4

Wie spärlich ist dieses Array? Wenn große Mengen leeren (ungenutzten) Speicherplatzes darin sind, möchten Sie vielleicht einen anderen Ansatz wählen. Die Antwort auf diese Frage schlägt eine STL-Karte vor.

Wenn es nicht spärlich ist (wie in den Kommentaren erwähnt), sollten Sie sich eine Sache ansehen, da Sie unter Windows ein Speicherkarten-Datei . Obwohl Ihr Betriebssystem 32-Bit sein kann, ist Ihr Dateisystem nicht. Dies bedeutet natürlich, dass es einen Austausch geben wird, der jedoch viel langsamer sein kann, als wenn Sie das ganze verdammte Ding wirklich in RAM stecken könnten.

Sie sollten auch wirklich daran denken, den RAM-Speicher des Systems auf das Maximum zu bringen (3GB auf 32-Bit-Windows, glaube ich), um zu sehen, ob es das für Sie behebt. Das sollte Sie nur etwa 100 Dollar kosten, und Sie geben viel mehr als das in Mannstunden aus, nur darüber beunruhigend.

    
T.E.D. 18.03.2010 20:04
quelle
3

Aus der Sicht Ihres Programms haben Sie immer 2 GB beim Start zur Verfügung, egal was sonst noch im System passiert. Ich glaube nicht, dass Windows eine Möglichkeit bietet, zu erkennen, ob Speicher auf die Festplatte ausgelagert wird oder nicht. Soweit es Datenstrukturen gehen, klingt es so, als würden Sie etwas Ähnliches beschreiben, wie eine Deque in der STL implementiert ist.

    
tloach 18.03.2010 19:59
quelle
1

std :: deque macht genau das, was Sie beschreiben, aber normalerweise in der Granularität der OS-Seitengröße (das heißt, die Blöcke, die es zuweist, sind normalerweise 4 kB).

Wenn Sie mit der Standardleistung von deque nicht zufrieden sind, können Sie möglicherweise einen benutzerdefinierten Zuordner schreiben, der größere Teile abgreift - dh 1 MB oder mehr gleichzeitig erhält.

Wie andere bereits gesagt haben, ist der virtuelle Adressraum Ihres Prozesses völlig unabhängig von allen anderen Prozessen, so dass Sie unabhängig von den sonstigen Vorgängen in Ihrem System 2 GB adressieren können. Das Betriebssystem tauscht Ihre Speicherseiten nach Bedarf auf die / von der Festplatte aus, um den Beschränkungen des installierten Speichers und aller dafür konkurrierenden Prozesse gerecht zu werden. Dies geschieht bei einer Seitengröße von 4 kB, unabhängig davon, wie groß Ihre Stücke sind.

    
Drew Hall 19.03.2010 12:48
quelle

Tags und Links