如何在cpp中创建固定大小(就内存而言)哈希表?

时间:2015-12-23 03:18:41

标签: c++ hash hashtable

我正在处理大量基于某些输入生成浮点的计算。如果我确实缓存这些数量,似乎可以优化相当多的重复调用。问题是,我不想缓存超过一定数量的内存使用量(即10GiB)。有没有办法在定义哈希映射时定义,或者每次将元素添加到地图时动态测试?

2 个答案:

答案 0 :(得分:2)

实现此目的的一种方法是实现LRU缓存(“最近最少使用”),它允许您始终修剪已被反馈最长时间的元素。对于某些使用模式,这可以优化下一个项目仍然在缓存中的概率。

设计一个LRU缓存曾经是一个常见的访谈问题(也许它仍然是),所以有很多SO答案等待找到。 This one看起来相当完整。

但那不是我会怎么做的。 10 GiB有很多内存,您可以在该空间中保留大量条目。如果您可以消除开销并保留两倍的缓存条目,则可能值得牺牲LRU缓存的精度。并且消除开销也可以累积地节省足够的周期来抵消具有非最佳缓存修剪策略所花费的周期。无论如何,LRU可能不是您的问题的最佳选择。谁知道?

使用良好的哈希函数和大哈希表,您可以使用替代策略:只需为每个哈希值保留一个条目。该解决方案的优点是它几乎为零开销。不需要时间戳,甚至不需要存储桶列表指针。无需在链中进行跟踪以查看条目是否在缓存中;第一个匹配是要替换的条目或条目。实际上,如果您的条目不是太大,那么可以轻松地将您可用的条目数量增加一倍。

对于稍微更精确的解决方案,您可以为每个哈希值保留两个条目,有点像简化的布谷鸟哈希。同样,没有存储开销(只要最终使用每个散列值),并且只有更多的查找成本。 (实际上非​​常少,因为两个条目都应该位于相同的内存缓存行中。)为了获得类似LRU行为的东西,在此变体中,如果找到的缓存条目是散列值的第二个条目,则交换这两个条目。 (事实上​​,在第一个条目不是你需要的条目之后交换这两个条目;然后你要么使用或替换现在是第一个条目的条目。)

C ++标准库没有非链式哈希表,但数据结构非常简单,几乎不需要库支持。库可能具有哪些有用的是哈希支持。 (有关更多哈希值,请参阅boost.hash,如果您的密钥为std::pairstd::tuple,则会特别有用。)

除此之外,您真正需要的是一组键值对,其大小可以调整为您想要在缓存中抛出的内存量。初始化这个数组有一个小皱纹:它需要初始化为某些东西,通常是默认的键和值构造函数产生的东西。但是对应于默认密钥的实际槽要么需要具有正确的值(不太可能是默认值),要么需要将其更改为具有不同哈希值的不同密钥。

答案 1 :(得分:1)

为每个条目存储时间戳,并密切关注哈希表'capacity,当它接近边界值时,刷新旧条目。