如何将哈希函数输出映射到布隆过滤器索引?

时间:2012-07-27 00:49:14

标签: c++ database algorithm bloom-filter

有人可以通过提供关于哈希函数输出如何映射到布隆过滤器索引的大纲来帮助我吗?以下是bloomfilters的概述。

1 个答案:

答案 0 :(得分:9)

  

关于散列函数输出如何映射到布隆过滤器索引的概述

对于每个正在使用的 k 哈希函数,它们映射到bloom过滤器中的一个位,就像哈希映射到哈希表中的哈希桶一样。所以,通常你可能会说一个哈希函数生成32位整数,然后使用模%运算符得到一个索引0 << i < n,其中n是你绽放的位数过滤

为了使其具体化,假设哈希函数生成0到2 ^ 32-1之间的数字,并且在bloom过滤器中有1000位:

int bit_index = hash_function(input_value) % 1000;

重要的是要注意,2 ^ 32-1大于1000.假设散列函数生成相当均匀分布的数字,但仅在0到1023之间(含),然后在模数运算之后它的两倍与24..999相比,bit_index将在0..23范围内(因为例如输入2和1002都导致后模数值为2,但只有25的输入产生25的输出)。因此,如果您有一个生成32位的哈希函数,您可能希望使用一个大小为2的幂的位数的布隆过滤器,然后切出哈希值的部分以使用,就像独立的哈希函数一样 - 所有在您链接的维基百科文章中都有解释。这需要一个高质量的散列函数,因为散列函数中的任何“聚类”缺陷都将通过未缓冲的输出传递给输出;具有素数位是减轻这种不良散列的一种方法。尽管如此,使用良好的散列函数,2的幂也可以很容易地使用按位AND运算提取位索引,并且 - 如果需要 - 位移位,这可能比整数模数更快,尽管散列函数可能会使这个问题相形见绌。整体表现形象。

编辑 - 处理评论......

假设您的MD5函数返回unsigned char*“p”到MD5_DIGEST_LENGTH个字节的数据,我建议您尝试:

BOOST_STATIC_ASSERT(MD5_DIGEST_LENGTH >= sizeof(int));
int bit_index = *reinterpret_cast<unsigned int*>(p) % num_of_bloom_filter_bits;

这实际上是一个特别糟糕的主意 - 抱歉 - 我会在一瞬间解释原因的两个原因。首先,回答你关于它的作用的问题:如果传递的表达式已经评估为BOOST_STATIC_ASSERT()false旨在给你一个编译错误。在这里,它基本上是一种记录MD5_DIGEST_LENGTH - MD5哈希文本表示的字符大小 - 的要求至少与系统用于{{1整数类型。 (该大小可能是4个字节,但可能是8.)该要求旨在确保下一行中的int是安全的。这样做是从MD5哈希的文本表示开始处的字节读取一个值,就好像这些字节包含reinterpret_cast一样。因此,假设您的int尺寸 4,MD5哈希是“0cc175b9c0f1b6a831c399e269772661”,如评论所示:前4个字节包含“0cc1”。该文本的ASCII代码为48,99,99,49十进制。当它们被读入int时,根据CPU的字节顺序,值可能会有所不同,但基本上你会得到其中一个数字乘以256 ^ 3再加上另一个256 ^ 2加上第三次256加上最终的数字。

我说这个原因特别糟糕的原因是:

  • MD5字符串中的每个字符都是数字(ASCII代码48-57)或“a”到“f”(97-102)的字母。这16个值只是一个字节可以具有的变化的16,并且当你生成的int值占用32位时,你实际上只得到2 ^ 16个不同的值。
  • 在某些计算机上,int必须与内存地址对齐,该地址是2,4,8等的倍数。int - 如果文本恰好从不兼容的地址开始,可能会崩溃你的电脑。注意:英特尔&amp; AMD没有这样的对齐要求,尽管它们可以更快地对正确对齐的数据进行操作。

所以,另一个建议是:

reinterpret_cast

这里,如果md5表示比数据缓冲区短,那么只会安全地复制它的初始部分,因此不需要BOOST_STATIC_ASSERT。

使用非加密哈希函数要容易得多,因为它们通常只返回一个数字而不是数字的可读文本缓冲区表示,因此您可以避免所有这些无意义。