结论1——表长大小
在所有情况下,表的大小都应与哈希中的最大键数成正比:更多,您浪费的内存过多,并且会降低缓存效率。更少,在某些时候哈希变得很慢。
比例的最佳常数取决于许多因素,例如您希望如何平衡内存消耗/速度权衡、哈希表的详细信息以及您的计算机体系结构。
如果使用开放寻址哈希,通常建议将表大于项目数的 1.2 倍,以控制冲突数。
如果使用单独的链接哈希,则可以使用较小的表(因为没有探测),但小于项目数 1 倍的任何内容都不常见,因为与用于键链的内存相比,用于表的内存可以忽略不计,而使用较大的表的性能可能会更好。
因此,无论哪种情况,表大小至少是哈希中项目数的 1.2 倍都是合理的,但如果你想要以更多内存使用为代价获得更快的哈希,则可以使用更大的表;最快的表可能会通过大约 2 倍于哈希中项目数的表大小来实现。
英语原文
In all cases, the size of the table should be kept proportional to the maximum number of keys in the hash: more and you waste more memory than necessary and you will reduce cache efficiency. Less and at some point the hash becomes slow.
The optimal constant of proportionality depends on many factors, such as how you wish to balance the memory consumption/speed tradeoff, the details of the hash table, and your computer architecture.
If you use an open addressing hash, it is generally recommended to keep the table larger than 1.2 times the number of items, to keep the number of collisions in check.
If you use a separate chaining hash, you can get away with smaller tables (because there is no probing), but anything smaller than 1 times the number of items is uncommon, because the memory used for the table would be negligible compared to the memory used for the key chains, while the performance could be better by using a larger table.
So in either case, it is reasonable to have the table size be at least 1.2 times the number of items in the hash, but if you want a faster hash at the cost of more memory usage, you can use a larger table; the fastest table will probably be achieved with a table size of about 2 times the number of items in the hash.
原文地址
结论2——为素数
Thomas Shürger的回答非常好,但是我要说一些不同的话。许多涉及哈希表的教科书都是由 70 年代到 90 年代学习的人编写的。
现在是 2018 年,默认情况下不应使用素数大小的哈希表。
你看,在过去,这个想法是使用一个便宜的哈希函数,然后通过素数计算它的模数来克服哈希的缺陷。最后的模运算是除法指令。
在那些日子里,整数乘法和整数除法的成本大致相同。今天,硬件已经改进,整数除法的成本大约是乘法的 9 倍,是整数加法或逻辑运算的 25 倍。
权衡已经改变,使用更复杂的哈希函数并使用 2 次幂哈希表大小比使用素数更好地利用 CPU 时间。
此外,由于矢量指令,计算两个或四个哈希函数与计算一个哈希函数一样便宜。这意味着使用多个哈希函数(例如线性哈希、二次哈希或现代变体,如布谷鸟哈希)的哈希表设计再次具有竞争力。
(说到指令集,非常现代的CPU具有CRC或加密指令,如果您知道自己在做什么,则可以从中构建非常便宜的哈希函数。
当然,你不应该相信我的话。始终测量。我做过一次,我发现一个在内部循环中使用标准C++无序集合数据结构的程序花了 20% 的时间做除法指令。用我自己的二次幂哈希表替换它使整个程序的速度提高了 15%。
这只是一个数据点,可能是一个极端情况,但它是说明性的。
原文链接