在C ++ std :: unordered_map中预分配存储区

时间:2011-05-05 23:27:35

标签: c++ unordered-map buckets

我正在使用gnu ++ 0x中的std::unordered_map来存储大量数据。我想为大量元素预先分配空间,因为我可以限制使用的总空间。

我希望能够做的是致电:

std::unordered_map m;
m.resize(pow(2,x));

其中x是已知的。

std::unordered_map不支持此功能。如果可能的话,我宁愿使用std::unordered_map,因为它最终会成为标准的一部分。

其他一些限制:

需要可靠的O(1)访问和地图变异。期望的散列和比较函数已经是非标准的并且有些昂贵。 O(log n)突变(与std::map一样)太昂贵了。

- >昂贵的哈希和比较也使基于摊销的增长方式过于昂贵。每个额外插入都需要来自这些函数的O(n)运算,这会在算法的运行时间内产生额外的二次项,因为指数存储需求需要O(n)增长。

5 个答案:

答案 0 :(得分:31)

m.rehash(pow(2,x));

如果pow(2, x)是您想要预先分配的存储区数量。你也可以:

m.reserve(pow(2,x));

但现在pow(2, x)是您计划插入的元素数量。这两个函数除了预分配桶之外什么都不做。它们不插入任何元素。它们都可以完全用于您的用例。

注意:您不能保证获得完全pow(2, x)个桶。一些实现将仅使用多个桶,其是2的幂。其他实现将仅使用素数桶。还有一些人将仅使用素数的子集来表示桶的数量。但无论如何,实现应该接受你想要的桶数提示,然后在内部向上舍入到下一个可接受的桶数。

以下是最新的(N4660)用于指定rehash的参数的准确措辞:

a.rehash(n)后置条件: a.bucket_count() >= a.size() / a.max_load_factor() and a.bucket_count() >= n

此后置条件可确保bucket()_count() >= nload_factor()保持小于或等于max_load_factor()

后来reserve(n)是根据rehash(n)

定义的

a.reserve(n):与a.rehash(ceil(n / a.max_load_factor()))相同。

答案 1 :(得分:5)

我认为无序地图有预先分配的内存并不重要。预计STL将是O(n)摊销的插入时间。在我看来,除非你知道这是代码的瓶颈,否则请自己省去编写自己的分配器的麻烦。

答案 2 :(得分:3)

我建议为std::unordered_map编写自己的分配器,以完全按照你想要的方式分配内存。

答案 3 :(得分:1)

构造函数采用参数" size_type bucket_count"根据{{​​3}}

因此,执行示例代码所说的最简单的方法是:

std::unordered_map m{ pow(2,x) };

这样会更有效率,因为它未定义在构造上将保留多少桶,否则它可能必须分配,然后在您之后调用reserve时释放。

答案 4 :(得分:-2)

我认为 rehash reserve 只有在事先知道映射值需要多少内存时才会起作用。如果映射的值很复杂或动态地改变大小(例如向量),则需要您自己的实现。例如,如果您的内存大小允许,您可以保留可能存在的最大容器。