【问题标题】:What's a fast ideal hash function for int32?什么是 int32 的快速理想散列函数?
【发布时间】:2016-02-22 06:50:25
【问题描述】:

我需要理想的(无冲突)哈希函数将 int 映射到相同大小的 int。最简单的方法是交换一些位的位置,但也许有一些很好的快速实现,操作数少,哈希种子容易改变? 也许使用一些快速对称密码? x86 有AES 指令。我不需要可移植性,所以使用 SSE 或其他 x86 特定加速指令的东西会很棒吗?因为散列应该非常快。

【问题讨论】:

  • 为什么要将int 映射到int,这根本没有任何意义。是因为数组有间隙吗?也许还有其他基于算术的解决方案!
  • 是的 - 你能解释一下你需要这个散列函数吗?否则,标识函数(只是将“x”映射到“x”)听起来符合您的要求 - 它将整数映射到相同大小的整数,没有冲突,而且非常非常快:)
  • @psmears 你又错过了一个非常
  • @iharob: 是的,但前提是你真的很好地优化它;-)
  • 一个简单的非聚类是% table size 并确保table_size 是一个素数。这不会损害一个好的哈希。它通常有助于一个糟糕的哈希。 YMMV。

标签: c optimization hash


【解决方案1】:

使用像FNV32-1A 这样的简单哈希可能会得到更好的结果。

crc32clmulaes 等复杂指令具有更高的吞吐量,但它们也可能具有更高的延迟。就其本身而言,它们也不一定会为您提供更好的分布。

您应该考虑的另一件事是冲突与散列函数的成本。线性探测通常应该在合理数量的探测中表现良好,因为 16 个值将适合单个高速缓存行。 CPU 可能还能够通过预测缓存访问来隐藏访问成本。

同样值得考虑的是入住率和餐桌大小之间的权衡。有时将表格大小加倍会更有效。

【讨论】:

  • 谢谢。我意识到没有必要使用理想的散列,简单的散列就可以了。目前我尝试了 crc32,它通过将未命中计数减少 10000 倍,使我在集群值上的性能提高了 10 倍,现在性能符合我的需求,每个核心大约 20-30M 查询。也许我也会对其他功能进行基准测试。
  • @user1940679 如果我没记错的话crc32 的吞吐量是一个周期,但延迟大约是三个周期。
  • 你能推荐一些关于英特尔低级优化的好书吗?我对这些事情很陌生。如果我有几条不使用 crc32 数据的指令,那么延迟应该不会产生影响,是吗?我也从下面的答案中尝试了哈希,crc32 指令更快,所以我认为在 int2int 哈希中没有办法超越它
  • @user1940679 英特尔manuals 非常全面。管道可能能够隐藏 crc32 指令的延迟,但这取决于工作负载。
【解决方案2】:
uint32_t hash( uint32_t value )
{
    return( value * 0xdeece66d + 0xb );
}

【讨论】:

  • 虽然这是一个答案,但我看不出它比任何其他 ax + b 散列方法更好或更差的原因(并且在不了解输入的情况下,您可以直接使用 value ,或者稍微旋转一下,效果一样)。
  • @ShadowRanger 它为任何输入大小生成 1 对 1 映射。换句话说,如果您将value 限制为 10 位并将返回掩码为 10 位,那么您将获得 10 位值之间的 1 对 1 映射。相比之下,乘数和加数的选择不好,例如return( value * 8 + 4 ) 不会生成一对一的映射。
  • 嗯,是的。但我很确定任何素数乘数都可以正常工作。一般来说,一个魔法素数并不比另一个好。
  • @ShadowRanger 这些特定的数字可以追溯到 Commodore Amiga,目前在 Java's java.util.Random 中使用
  • 鉴于 OP 正在使用这个 mod,添加一个常量并没有帮助,它只是“旋转”表索引,它不会分散集群。所以只是乘法同样好
猜你喜欢
  • 2011-12-17
  • 2014-03-30
  • 2012-09-24
  • 1970-01-01
  • 1970-01-01
  • 2015-10-10
  • 1970-01-01
  • 1970-01-01
  • 2011-12-03
相关资源
最近更新 更多