在C ++中用`std :: unordered_set`设置初始桶数的策略

时间:2016-07-20 11:06:48

标签: c++ data-structures

如果我们知道我们要在mn项之间进行哈希,其中mn相对较大,那么' sa设置std::unordered_set初始存储桶数量的合理策略?如果它有帮助,就我而言m=n/2。一般来说,我希望优化速度,但却无法承受不合理的内存量。提前谢谢。

2 个答案:

答案 0 :(得分:2)

tl; dr没有简单的答案。无论是测量,还是让容器自动管理铲斗尺寸。

正如我在评论中试图说的那样,变量太多了,而你似乎并没有意识到自己有多模糊。你花了一个小时甚至说出你感兴趣的实现。

mn“相对较大”......相对于什么?

“这是唯一的两个操作,我希望它们能够快速完成。”快速定义?什么速度够快?什么太慢了?你有没有测量过?

如果你想最小化负载系数,那么每个桶平均不超过一个元素(因此,一旦知道了正确的存储桶,就不需要通过存储桶进行迭代),那么你需要 at至少 n桶。但是这并不能保证每个元素有一个存储桶,因为用于从哈希码中确定存储桶的函数可能会为放入容器中的每个指针返回相同的值。知道这是否可能取决于正在使用的散列函数,以及将散列码映射到桶的函数,以及指针值本身。

对于GCC,指针的哈希函数是标识函数。对于默认的unordered_map实现,映射到桶是hash_function(x) % bucket_count(),并且桶计数始终是素数,以减少冲突的可能性。如果您在哈希映射中存储的地址往往被桶数的倍数分隔,那么它们将最终在同一个桶中。知道这有多大可能取决于用于n的桶数(你没有说明)和你正在使用的指针值的分布(你没有说明)。

如果您使用了解预期存储的指针值的自定义哈希函数,那么您可以使用在[0, n)之间均匀分布的完美哈希函数,然后将bucket_count()设置为{{ 1}}并确保没有碰撞。

但是确保每个桶只有一个元素是值得的,这是不明显的,因为它使用更多的内存。在大多数程序中,通过包含两个或三个元素的存储桶进行迭代不会成为瓶颈。也许它会出现在你的身上,这是不可能知道的,因为你没有说出你想要的东西,除非它必须快速。哪个是模糊的,没有意义。

回答这些问题的唯一方法是让您衡量真实世界的表现,没有人可以根据您的模糊要求为您提供一个可以使您的代码更快的神奇数字。 如果有一个简单的答案,总是让“相对大”的元素数量更快,那么标准库实现应该已经做到了,所以你只是在浪费时间做同样的事情用手。

答案 1 :(得分:0)

作为替代方案,如果您可以使用对数性能(通常不是问题),请改用std :: map。然后,您可以在100%的时间内保证查找复杂性,无需重新散列。非常有用的属性,例如在硬实时系统中。