【问题标题】:Too many collisions in hash function哈希函数中的冲突太多
【发布时间】:2014-10-02 23:46:39
【问题描述】:

我试图将大约 6400 万个 64 位唯一无符号整数散列到 1.28 亿个桶(27 位宽地址)。我尝试了 Bob Jenkin 的 HashLittleMurmur 哈希(这两个哈希函数都提供了 32 位哈希,我将其屏蔽以获得 27 位地址)。在这两种情况下,它导致了大约 22% 的碰撞,最终只占用了 37% 的存储桶。这是预期的还是我做错了什么?我期待更少的碰撞和更好的存储桶占用。

【问题讨论】:

  • 而不是掩码 - 我假设你的意思是与 0x7FFFFFF 进行 AND'ing - 尝试取最大素数的模数
  • 大多数著名的散列函数都是为散列短到中等长度的字符串而设计的。对于整数数据,值本身通常是最好的哈希值,而要将 64 位减少到 32 位,您可以使用混合函数,否则将用于聚合哈希值。
  • 可能值得玩一下stackoverflow.com/questions/664014/… 中的一些哈希函数?
  • 如果您使用的是 Intel,那么基于 CRC-32 的东西可能值得一试:_mm_crc32_u32()。见stackoverflow.com/a/3045334/2809095
  • 有人可以提供一些关于设计混合功能的参考吗?

标签: c algorithm hash collision murmurhash


【解决方案1】:

使用基于http://en.wikipedia.org/wiki/Poisson_distribution 的近似值,它看起来比我随机预期的要差一些。如果一个桶中的预期条目数是 1/2,我预计 0 个条目的概率大约是 exp(-0.5) = 0.607,而一个桶中 1 个条目的概率大约是这个的一半,即 0.303。这样一来,一个桶有两个或更多条目的概率为 0.09。

你的整数都是唯一的吗?如果不是,您是否将重复值计算为导致哈希冲突?

在有利的情况下,您可以选择一个散列函数,以便随机产生更少的冲突。有时 hash(x) = x % p,其中 p 是素数,会实现这一点。

【讨论】:

    【解决方案2】:

    如果您想获得“随机但可重复”的结果 - 即使对于故意困难的输入也具有最佳的最坏情况碰撞率* - 您可以简单地创建如下表格:

    uint32_t r[8][256];
    

    使用 8kb 的随机数据填充它 - 您可以使用 google 搜索具有随机数据的网站以下载并重新格式化它以包含在您的源中或在运行时从文件中加载。

    (*) - 只要输入不是由知道您的随机数据的恶意人员创建的。

    然后像这样散列:

    uint32_t hash(uint64_t n)
    {
        unsigned char* p = (unsigned char*)&n;
        return r[0][p[0]] ^ r[1][p[1]] ^ r[2][p[2]] ^ r[3][p[3]] ^
               r[4][p[4]] ^ r[5][p[5]] ^ r[6][p[6]] ^ r[7][p[7]];
    }
    

    当然,更好的最坏情况碰撞通常与更好的实际性能完全不同——很大程度上取决于你的数据集和硬件——所以如果你真的在乎,它只是作为基准测试的东西。也可以对简单的传递进行基准测试。使用质数的桶是非常好的做法,但根据您的哈希表可能会很棘手 - 例如一些实现可能会将任何调整大小请求四舍五入到 2 的幂。

    【讨论】:

      猜你喜欢
      • 2019-03-25
      • 1970-01-01
      • 1970-01-01
      • 2019-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-13
      • 1970-01-01
      相关资源
      最近更新 更多