布隆过滤器对面?

时间:2009-03-11 18:18:01

标签: data-structures bloom-filter

我正在尝试优化一个基本上运行数百万次测试的软件。这些测试的生成方式可能会有一些重复。当然,如果我能有效地避免它,我不想花时间运行我已经运行过的测试。

所以,我正在考虑使用Bloom过滤器来存储已经运行的测试。但是,Bloom过滤器对我来说不安全。它给出了误报。也就是说,它可能会报告我已经进行了一项我没有进行的测试。虽然这在我正在研究的场景中是可以接受的,但我想知道是否有相当于Bloom过滤器,但在相反的方面犯了错误,即只给出假阴性。

我没有运气就浏览了文献。

9 个答案:

答案 0 :(得分:24)

是的,有损哈希表或LRUCache是​​一种具有快速O(1)查找的数据结构,只会给出假阴性 - 如果你问“我是否运行测试X”,它会告诉你“是” ,你肯定有“,或”我不记得了。“

原谅非常粗糙的伪代码:

setup_test_table():
    create test_table( some large number of entries )
    clear each entry( test_table, NEVER )
    return test_table

has_test_been_run_before( new_test_details, test_table ):
    index = hash( test_details , test_table.length )
    old_details = test_table[index].detail
    // unconditionally overwrite old details with new details, LRU fashion.
    // perhaps some other collision resolution technique might be better.
    test_table[index].details = new_test_details
    if ( old_details === test_details ) return YES
    else if ( old_details === NEVER ) return NEVER
    else return PERHAPS    

main()
    test_table = setup_test_table();
    loop
        test_details = generate_random_test()
        status = has_test_been_run_before( test_details, test_table )
        case status of
           YES: do nothing;
           NEVER: run test (test_details);
           PERHAPS: if( rand()&1 ) run test (test_details);
    next loop
end.

答案 1 :(得分:14)

完成此任务的确切数据结构是Direct-mapped cache,通常用于CPU中。

function set_member(set, item)
    set[hash(item) % set.length] = item

function is_member(set, item)
    return set[hash(item) % set.length] == item

答案 2 :(得分:6)

是否可以存储运行的测试?这应该反过滤器的行为。

答案 3 :(得分:1)

  1. 如上所述,使用位集。如果你知道没有。在您预先运行的测试中,您将始终从数据结构中获得正确的结果(存在,不存在)。
  2. 你知道你要用什么键进行散列?如果是这样,你应该运行一个实验来查看BloomFilter中键的分布,这样你就可以对它进行微调以重现误报,或者你有什么。
  3. 您可能也想检查HyperLogLog。

答案 4 :(得分:0)

不,如果你考虑一下,它就没那么有用了。在你的情况下,你无法确定你的测试运行是否会停止,因为如果总是存在“假阴性”,那么总会有需要运行的测试......

我会说你只需要使用哈希。

答案 5 :(得分:0)

LRUCache怎么样?

答案 6 :(得分:0)

对不起,我没多大帮助 - 我认为不可能。如果无法排序测试执行,可以使用打包格式(每个字节8个测试!)或一个好的稀疏数组库,用于将结果存储在内存中。

答案 7 :(得分:0)

我认为你遗漏了部分解决方案;为了完全避免误报你仍然需要跟踪哪些已经运行,并且基本上使用布隆过滤器作为快捷方式来确定测试肯定还没有运行。

尽管如此,由于您事先知道了测试的数量,因此您可以使用一些众所周知的公式来确定过滤器的大小,以便提供可接受的错误率。如果返回假阳性的概率为1%,则需要~9.5位/条目,因此对于一百万个条目,1.2兆字节就足够了。如果将可接受的错误率降低到0.1%,则仅增加到1.8 MB。

维基百科文章Bloom Filters提供了一个很好的分析,并对所涉及的数学进行了有趣的概述。

答案 8 :(得分:-1)

您期望的数据结构不存在。因为这样的数据结构必须是多对一映射,或者说是有限状态集。必须至少有两个不同的输入映射到相同的内部状态。所以你不知道它们中是否有两个(或更多)都在集合中,只知道至少有一个这样的输入存在。

EDIT只有在寻找内存有效的数据结构时才会出现这种情况。如果内存不受限制,您可以通过存储每个成员项来始终获得数据结构以提供100%准确的结果。