Pre-allocating Eimer in einer C++ - std::unordered_map
Ich bin mit der std::unordered_map
von gnu++0x speichern einer großen Menge von Daten. Ich will pre-Zuordnung von Speicherplatz für die große Anzahl von Elementen, da ich gebunden der gesamte Speicherplatz verwendet.
Was ich möchte in der Lage sein zu tun ist, rufen Sie:
std::unordered_map m;
m.resize(pow(2,x));
wo x bekannt ist.
std::unordered_map
dies nicht unterstützt. Ich würde eher std::unordered_map
wenn möglich, da er schließlich Teil des Standards.
Einige andere Einschränkungen:
Müssen zuverlässig O(1) der Zugriff und die mutation von der Karte. Die gewünschte hash und Vergleich der Funktionen sind bereits nicht-standard-und etwas teuer. O(log n) mutation (wie bei std::map
) ist zu teuer.
-> Die teuren hash und Vergleich auch Abschreibungen-basiert Wachstum viel zu teuer. Jedes extra einfügen erfordert O(n) Operationen von Funktionen, die Ergebnisse in einem zusätzlichen quadratischen term in der der Algorithmus die Laufzeit, da der exponentielle Speicherbedarf benötigen O(n) Wucherungen.
Du musst angemeldet sein, um einen Kommentar abzugeben.
wenn
pow(2, x)
ist die Anzahl der buckets, die Sie möchten, reserviert. Sie können auch:aber jetzt
pow(2, x)
ist die Anzahl der Elemente, die Sie planen, einführen. Die beiden Funktionen nichts zu tun, sondern preallocate Eimer. Sie don ' T fügen Sie beliebige Elemente. Und Sie sind sowohl dazu genutzt werden, um genau für Ihren Anwendungsfall.Hinweis: Sie sind nicht garantiert, um genau
pow(2, x)
Eimer. Einige Implementierungen verwenden Sie nur eine Reihe von Eimern, die eine Potenz von 2 ist. Andere Implementierungen verwenden Sie nur eine prime Anzahl der buckets. Wieder andere verwenden nur eine Teilmenge der Primzahlen, für die Anzahl der buckets. Aber in jedem Fall, die Umsetzung sollte akzeptieren Ihre Hinweis bei der Anzahl der Perioden, die Sie wünschen, und dann intern die Runde bis zum nächsten akzeptablen Anzahl von Eimern.Hier ist die genaue Formulierung, dass die neueste (N4660) verwendet, um das argument zu
rehash
:a.rehash(n)
: Postconditions:a.bucket_count() >= a.size() /a.max_load_factor() and a.bucket_count() >= n
.Diese postcondition sorgt dafür, dass
bucket()_count() >= n
, und dassload_factor()
bleibt weniger als oder gleichmax_load_factor()
.Anschließend
reserve(n)
ist definiert in Bezug aufrehash(n)
:a.reserve(n)
: Wiea.rehash(ceil(n /a.max_load_factor()))
.Ich glaube nicht, dass es darauf ankommt, für eine ungeordnete map, pre-allocated memory. Die STL wird erwartet, dass O(n) amortisiert einlegen Zeit. Sparen Sie sich das lästige schreiben Ihrer eigenen allocator, bis Sie wissen, dies ist der Flaschenhals des Codes, meiner Meinung nach.
Ich würde vorschlagen, das schreiben Ihrer eigenen allocator für die
std::unordered_map
dass Speicher reserviert, genau so, wie Sie wollen.Der Konstruktor nimmt einen parameter "size_type bucket_count" nach http://en.cppreference.com/w/cpp/container/unordered_map/unordered_map
so ist der einfachste Weg, das zu tun, was dein Beispiel code sagt, ist:
Diese werden effizienter, da es undefiniert, wie viele buckets reserviert wird auf die Bau-andernfalls kann es zu reservieren und dann freigeben, wenn Sie anrufen, reservieren danach.
Ich denke rehash und reserve beide funktionieren nur, wenn Sie im Voraus wissen, wie viel Speicher Ihr zugeordnete Wert wird. Wenn der zugeordnete Wert ist kompliziert oder dynamisch seine Größe ändert (z.B. ein Vektor), dann müssen Sie Ihre eigene Implementierung. Zum Beispiel, wenn Ihre Speicher-Größe ermöglicht es, Sie berechtigt ist, den größten container, kann immer passieren, zu existieren.
sizeof(std::vector<T>)
bleibt die gleiche (für den gleichenT
offensichtlich). Diemap
reserviert, die genaue Menge an Speicherplatz für einestd::vector
1 element oder einestd::vector
1 mil Elemente. "Sie können behalten uns das größte container-das kann immer passieren, zu existieren" ist ein weiterer Punkt, dass ich nicht als eine fundierte Beratung, die im Zusammenhang mit dieser Frage.