实际上,即使考虑了帐户缓存,Bloom过滤器真的比哈希更快吗?


16

当您考虑可以确定Int是否在恒定时间内具有99%的确定性的集合中时,Bloom过滤器看起来确实很棒。但是散列也是如此,唯一的区别在于,在散列中,大多数时候您只访问一次内存。使用Bloom过滤器时,您需要在完全遥远的地方每个请求访问它们约7次,因此每个请求将有多个缓存未命中。

我想念什么吗?


什么完全遥远的地方?只有m位。这可能适合单个寄存器,或者更糟的是单个高速缓存行。

1
@delnan AFAIK它使用大约10位/元素的内容,不是吗?因此,对于数千个元素(即巨大的数据存储区)来说,它绝对不适合放入缓存中。因此,如果您使用k哈希,则可能是k每次读取都有高速缓存未命中。另一方面,哈希表可确保您在大多数情况下都会得到0个高速缓存未命中的答案-无论如何,冲突很少发生。
MaiaVictor 2014年

您有k位,句号。所有元素都会影响相同的固定位数,这就是为什么误报率取决于条目数的原因。

Answers:


33

您缺少这两个数据结构如何处理哈希冲突。Bloom过滤器不存储实际值,因此所需的空间是指定数组的恒定大小。相反,如果您使用传统的哈希,它将尝试存储您提供的所有值,因此它会随着时间增长。

考虑一个简化的哈希函数(仅出于示例目的!)f(x) = x % 2。现在,您输入以下整数:2, 3, 4, 5, 6, 7

标准哈希:给定值将被散列,而且我们有很多冲突的结束,由于f(2) = f(4) = f(6) = 0f(3) = f(5) = f(7) = 1。尽管如此,哈希存储了所有这些值,它可以告诉您8未存储在其中。它是如何做到的?它跟踪冲突并存储具有相同哈希值的所有值,然后在查询时,它还会对查询进行比较。因此,让我们在地图上查询8f(8) = 0,以便将其放入我们已经插入的存储桶中,2, 4, 6并需要进行3次比较,以告诉您这8不是输入的一部分。

布隆过滤器:通常,每个输入值都针对k不同的哈希函数进行哈希处理。再次,为简单起见,我们假设仅使用单个哈希函数f。我们需要一个由2个值组成的数组,然后当遇到输入时,2这意味着由于f(2) = 0我们将位置的数组值设置0为value 1。同样的情况发生了46。类似地,3, 5, 7每个输入都将数组位置设置1为value 1。现在我们查询if是否8是输入的一部分:f(8) = 0位置0处的数组是1,因此Bloom筛选器将错误地声明8确实是输入的一部分。

为了更加现实,让我们考虑添加第二个哈希函数g(x) = x % 10。这样,输入值2将导致两个哈希值f(2) = 0g(2) = 2并且两个对应的数组位置将被设置为1。当然,数组现在至少应为size 10。但是,当我们查询时,8我们将检查数组8由于的位置g(8) = 8,并且该位置仍为0。这就是为什么其他哈希函数可以减少误报的原因。

比较: Bloom过滤器使用k哈希函数,这意味着最多可以k访问随机数组位置。但是这个数字是准确的。相反,哈希仅保证您享有摊销后的固定访问时间,但可能会根据哈希函数和输入数据的性质而退化。因此,除了退化的情况外,通常更快。

但是,一旦发生哈希冲突,标准哈希将必须对照查询值检查存储值的相等性。这种相等性检查可能会非常昂贵,并且对于Bloom Bloom过滤器将永远不会发生。

就空间而言,布隆过滤器是恒定的,因为不需要使用比指定数组更多的内存。另一方面,由于必须跟踪冲突值,因此哈希值会动态增长,并且可能变得更大。

权衡:现在您知道什么便宜,什么不便宜,在什么情况下,您应该可以看到权衡。如果您想非常快速地检测到以前已经看到过某个值,但可以使用误报,则Bloom过滤器非常有用。另一方面,如果希望以无法准确判断运行时为代价来确保正确性,则可以选择哈希图,但是可以接受偶尔退化的情况,这种情况可能比平均速度慢得多。

同样,如果您在有限的内存环境中,则可能希望使用bloom筛选器以保证其内存使用率。


好答案。这就是我的困惑。实际上,每个数据结构都有其最佳用例,不同的考虑取决于权衡。
理查德

确实有一个合适的例子是一个很好的解释。那么我们如何使用值“ k”呢?它是否取决于我们拥有的价值总数?
itsraghz

5

Bloom过滤器和哈希的用例是不同的,并且大多数情况下是不相交的,因此直接比较是没有意义的。此外,这将取决于实现的技术细节,因为有许多方法可以处理具有不同权衡的哈希冲突。

Bloom过滤器可以使用适度的内存以合理的概率(但不是完全正确)来回答元素是否在大型集中的集合中。庞大的元素多达数万亿。但是它们从来都不是精确的。您只能通过使用更多的内存或更多的哈希函数来减少误报的数量。

另一方面,哈希表是精确的,但它们需要存储集合。因此,数万亿个元素将需要TB的内存(而这仅仅是美国的数万亿美元)。他们还可以为每个元素存储额外的数据,而Bloom筛选器则不能。

因此,如果您使用缓慢的方法来获取大型集合(不适合内存或无法将其传输到客户端)的某个成员(涉及查询服务器,从磁盘中读取数据等)的数据,则可以使用布隆过滤器等),并希望避免对不在集合中的对象执行慢速操作。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.