32

鉴于 SSE 4.2(英特尔酷睿 i7 和 i5 部件)包含 CRC32 指令,调查是否可以构建更快的通用哈希函数似乎是合理的。据此,只有16 位 CRC32 是均匀分布的。那么还有什么其他的转变可以用来克服这个问题呢?

更新 这个怎么样?只有 16 位适合散列值。美好的。如果您的表是 65535 或更少,那就太好了。如果不是,则通过 Nehalem POPCNT(人口计数)指令运行 C​​RC 值以获取设置的位数。然后,将其用作表数组的索引。如果您的桌子位于 1 毫米条目以南,则此方法有效。我敢打赌,这比性能最好的哈希函数更便宜/更快。既然GCC 4.5具有 CRC32 内在特性,它应该很容易测试……如果我有足够的空闲时间来研究它。

大卫

4

5 回答 5

17

Revisited , August 2014
Arnaud Bouchez在最近的评论中提示,鉴于其他答案和评论,我承认需要更改原始答案或为最不合格的答案。最后,我将原样保留,以供参考。

首先,也许是最重要的,这个问题的公平答案取决于哈希码的预期用途:“好”[哈希函数...]是什么意思?哈希将在哪里/如何使用?(例如,它是用于散列相对较短的输入键吗?是用于索引/查找目的,生成消息摘要还是其他用途?所需的散列码本身有多长,所有 32 位 [CRC32 或其衍生物],更多位,更少......等等?
OP问题要求“更快通用哈希函数 ",所以重点是速度(CPU 密集度较低的东西和/或可以利用各种性质的并行处理的东西)。我们可能会注意到,哈希码本身的计算时间通常只是问题的一部分散列的应用(例如,如果散列码的大小或其固有特性导致许多冲突,需要处理额外的周期)。此外,“通用”的要求留下了许多关于可能用途的问题。

考虑到这一点,一个简短而更好的答案可能是:

的,CRC32C 在较新的英特尔处理器上的硬件实现可用于构建更快的哈希码;但请注意,根据散列的具体实现及其应用,由于冲突的频率以及需要使用更长的代码,总体结果可能不是最佳的。此外,当然,应该仔细审查哈希的加密使用,因为 CRC32 算法本身在这方面非常薄弱。

最初的答案引用了 Bret Mulvey 的一篇关于评估哈希函数的文章,正如 Mdlg 的答案所指出的,这篇文章的结论关于 CRC32 是错误的,因为它所基于的 CRC32 的实现是错误的/有缺陷的。尽管在 CRC32 方面存在重大错误,但本文提供了有关哈希算法一般属性的有用指导。这篇文章的 URL 现已失效;我在archive.today上找到了它,但我不知道作者是否在另一个位置有它,也不知道他是否更新了它。

这里的其他答案引用CityHash 1.0作为使用 CRC32C 的哈希库的示例。显然,这是在一些更长(超过 32 位)哈希码的上下文中使用的,但不适用于 CityHash32() 函数本身。此外,与生成哈希码的所有移位和混洗以及其他操作相比,City Hash 函数对 CRC32 的使用相对较少。(这不是对我没有实践经验的 CityHash 的批评。我将通过对 CityHash 函数产生良好的源代码的粗略审查,例如 ell 分布式代码,但没有明显更快比其他各种散列函数。)

最后,您还可以在关于 SO 的准重复问题中找到对此问题的见解。


原始答案和编辑(2010 年 4 月)

先验这听起来是个坏主意!.

CRC32不是为散列目的而设计的,它的分布可能不均匀,因此它是一个相对较差的散列码。此外,它的“加扰”能力相对较弱,导致单向哈希非常差,就像在加密应用程序中使用的那样。

[BRB:我正在寻找有关该效果的在线参考资料...]

Google 的第一个 [keywords = CRC32 distribution] 似乎证实了这一点:
Evaluating CRC32 for hash tables

编辑:上面引用的页面,实际上是完整的文章,为在 Hash 函数中寻找什么提供了一个很好的基础。
阅读 [快速] 这篇文章,确认了一般情况下不应将 CRC32 用作散列的一揽子声明,但是,根据散列的特定目的,至少部分可以使用 CRC32 作为一个哈希码。

例如,CRC32 代码的较低(或较高,取决于实现)16 位具有相对均匀的分布,并且只要不关心哈希码的加密属性(例如,类似密钥的事实)产生非常相似的代码),可以构建一个哈希码,例如,使用原始密钥的两半(或任何分割)产生的两个 CRC32 代码的低 [或高] 16 位的串联。
需要运行测试以查看内置 CRC32 指令相对于替代散列函数的效率是否会导致两次调用指令并将代码拼接在一起等的开销不会导致整体较慢的功能。

于 2010-04-22T21:48:15.280 回答
15

其他答案中提到的文章基于有缺陷的 crc32 代码得出了错误的结论。谷歌的排名算法还没有根据科学准确性进行排名。

与参考文章“Evaluating CRC32 for hash tables”的结论相反,CRC32 和 CRC32C 对于哈希表的使用是可以接受的。作者的示例代码在 crc32 表生成中存在 bug。修复 crc32 表,使用相同的方法得到令人满意的结果。此外,CRC32 指令的速度使其成为许多情况下的最佳选择。使用 CRC32 指令的代码在峰值时比最佳软件实现快 16 倍。(请注意,CRC32 与 intel 指令实现的 CRC32C 并不完全相同。)

CRC32 显然不适合加密使用。(32位是蛮力的笑话)。

于 2010-06-15T12:59:47.540 回答
4

是的。 CityHash 1.0.1包括一些使用 CRC32 指令的新“良好哈希函数”。

于 2011-04-29T05:21:55.100 回答
2

只要您不在加密哈希之后,它就可以工作。

于 2010-04-22T22:25:38.753 回答
2

出于加密目的,CRC32 是一个糟糕的基础,因为它是线性的(在向量空间GF(2)^32上)并且很难纠正。它可以用于非加密目的。

但是,最近的英特尔内核具有AES-NI指令,基本上在两个时钟周期内执行 AES 块加密的 1/10。它们在最新的 i5 和 i7 处理器上可用(有关详细信息,请参阅Wikipedia 页面)。看起来是构建加密散列函数的一个良好开端(并且对加密有益的散列函数也适用于其他任何事情)。

实际上,至少有一个SHA-3“第 2 轮”候选ECHO哈希函数)是围绕 AES 元素构建的,因此 AES-NI 操作码提供了非常显着的性能提升。(不幸的是,在没有 AES-NI 指令的情况下,ECHO 性能有些糟糕。)

于 2010-04-23T14:00:04.067 回答