python中快速、大宽度、非加密字符串哈希
我需要python中的一个高性能字符串哈希函数,该函数生成的整数至少有34位的输出(64位有意义,但32位太少)。还有其他几个问题类似于这个关于堆栈溢出的问题,但在我能找到的所有被接受/投票赞成的答案中,都属于少数几个类别中的一个,它们不适用(出于给定的原因)python中快速、大宽度、非加密字符串哈希,python,string,hash,high-speed-computing,Python,String,Hash,High Speed Computing,我需要python中的一个高性能字符串哈希函数,该函数生成的整数至少有34位的输出(64位有意义,但32位太少)。还有其他几个问题类似于这个关于堆栈溢出的问题,但在我能找到的所有被接受/投票赞成的答案中,都属于少数几个类别中的一个,它们不适用(出于给定的原因) 使用内置的hash()函数。这个函数,至少在我开发的机器上(使用python 2.7和64位cpu)生成一个32位以内的整数-不够大 使用hashlib。hashlib提供加密哈希例程,其速度远远低于非加密目的所需的速度。我发现这是不言
- 使用内置的
函数。这个函数,至少在我开发的机器上(使用python 2.7和64位cpu)生成一个32位以内的整数-不够大hash()
- 使用hashlib。hashlib提供加密哈希例程,其速度远远低于非加密目的所需的速度。我发现这是不言而喻的,但如果你需要基准和引用来说服你这个事实,那么我可以提供
- 使用
函数作为原型来编写自己的函数。我怀疑这将是正确的方法,只是这个特定函数的效率在于它使用了c_mul函数,该函数的长度约为32位—同样,对我来说太小了!非常令人沮丧,它如此接近完美李>字符串。\uuuu hash\uuuu()
def perturb_hash(key,n):
return hash((key,n))
最后,如果你想知道我到底在做什么,我需要这样一个特定的散列函数,我正在对pybloom模块进行完整的重写,以显著提高其性能。我成功地做到了这一点(它现在运行速度快了约4倍,占用了约50%的空间),但我注意到,有时如果过滤器足够大,它的假阳性率会突然飙升。我意识到这是因为哈希函数没有寻址足够的位。32位只能寻址40亿位(请注意,过滤器寻址的是位而不是字节),而我用于基因组数据的一些过滤器是这一数字的两倍或更多(因此最小值为34位)
谢谢 看一看。其中包括一些性能数据。应该可以将其移植到Python,纯或作为C扩展。(更新了作者建议使用128位变体,扔掉不需要的位)
如果64位哈希2适合您,则中有一个Python实现(C扩展),其中包括一些其他非加密哈希变体,尽管其中一些仅提供32位输出
更新我为Murruld3散列函数做了一个快速的Python包装。你可以在网上找到它;它只需要一个C++编译器来构建;不需要增压
使用示例和定时比较:
import murmur3
import timeit
# without seed
print murmur3.murmur3_x86_64('samplebias')
# with seed value
print murmur3.murmur3_x86_64('samplebias', 123)
# timing comparison with str __hash__
t = timeit.Timer("murmur3.murmur3_x86_64('hello')", "import murmur3")
print 'murmur3:', t.timeit()
t = timeit.Timer("str.__hash__('hello')")
print 'str.__hash__:', t.timeit()
输出:
15662901497824584782
7997834649920664675
murmur3: 0.264422178268
str.__hash__: 0.219163894653
“字符串”:我假定您希望对Python2.xstr
对象和/或Python3.x字节和/或bytearray
对象进行散列
这可能违反了你的第一个约束,但是:考虑使用像
之类的东西。
(zlib.adler32(strg, perturber) << N) ^ hash(strg)
(zlib.adler32(strg,扰动器)如果可以使用Python 3.2,那么64位窗口上的哈希结果现在是64位值
使用内置的hash()函数。至少在我为之开发的机器上(使用
Python2.7和一个64位cpu)生成一个32位以内的整数,这个整数的大小不足以
我的目的
不是这样。内置的哈希函数将在64位系统上生成64位哈希
这是来自Objects/stringobject.c
(python版本2.7)的python str哈希函数:
static long
字符串\u散列(PyStringObject*a)
{
寄存器Py_ssize_t len;
寄存器无符号字符*p;
寄存器长x;/*请注意64位哈希,至少在64位系统上是这样*/
如果(a->ob_shash!=-1)
返回a->ob_shash;
len=Py_尺寸(a);
p=(无符号字符*)a->ob_sval;
x=*p=0)
x=(1000003*x)^*p++;
x^=Py_尺寸(a);
如果(x==-1)
x=-2;
a->ob_shash=x;
返回x;
}
小心使用内置的哈希函数强>
自从Python3以来,每次解释器启动时都会给它注入不同的种子(我不知道更多的细节),因此每次它都会生成不同的值——但不会使用本机数字类型
$ python3 -c 'print(hash("Hello!"), hash(3.14))'
-1756730906053498061 322818021289917443
$ python3 -c 'print(hash("Hello!"), hash(3.14))'
-4556027264747844925 322818021289917443
$ python3 -c 'print(hash("Hello!"), hash(3.14))'
-4403217265550417031 322818021289917443
我一直在使用Python2.7,但是如果3.x引擎中的散列宽度是
$ python3 -c 'print(hash("Hello!"), hash(3.14))'
-1756730906053498061 322818021289917443
$ python3 -c 'print(hash("Hello!"), hash(3.14))'
-4556027264747844925 322818021289917443
$ python3 -c 'print(hash("Hello!"), hash(3.14))'
-4403217265550417031 322818021289917443