【问题标题】:Generating k pairwise independent hash functions生成 k 对独立的散列函数
【发布时间】:2012-08-20 15:53:24
【问题描述】:

我正在尝试在 Scala 中实现 Count-Min Sketch 算法,因此我需要生成 k 对独立的哈希函数。

这是一个比我以前编程过的任何东西都低的级别,而且我对哈希函数了解不多,除了算法类,所以我的问题是:我如何生成这些 k 成对独立的哈希函数?

我应该使用像 MD5 或 MurmurHash 这样的哈希函数吗?我是否只生成 f(x) = ax + b (mod p) 形式的 k 个哈希函数,其中 p 是素数,a 和 b 是随机整数? (即,universal hashing family 每个人都在算法 101 中学习)

我更追求简单而不是原始速度(例如,如果实现起来更简单,我会慢 5 倍)。

【问题讨论】:

  • MD5 是加密的。 MurmurHash 很好,但在密码学上不强。

标签: scala hash-function cryptographic-hash-function


【解决方案1】:

Scala 已经实现了MurmurHash(它是scala.util.MurmurHash)。它非常快速且非常擅长分配价值。加密哈希是多余的——你只需要比你需要的时间长几十或几百倍。只需选择 k 不同的种子作为开始,因为它在质量上几乎是加密的,你会得到 k 很大程度上独立的哈希码。 (在 2.10 中,您可能应该改用 scala.util.hashing.MurmurHash3;用法有很大不同,但您仍然可以通过混合来做同样的事情。)

如果您只需要将近值映射到随机远值,这将起作用;如果您想避免冲突(即,如果 A 和 B 使用哈希 1 发生冲突,它们可能不会也使用哈希 2 发生冲突),那么您至少需要再走一步,而不是对整个对象进行哈希处理,而是对它的子组件进行哈希处理。哈希有机会以不同的方式开始。

【讨论】:

  • 您关于避免冲突的观点是否意味着使用不同种子从 MurmurHash 生成的哈希函数不会(默认情况下)成对独立?我只是在我的情况下散列整数。
  • @grautur - 哦,整数就好了。我的意思是,如果对象 A 使用 .hashValue 散列到值 x 并且对象 B 也散列到值 x,那么无论您使用什么种子,A 和 B 都会发生冲突(当您从种子开始然后混合 x 时)。如果您对整数进行哈希处理,则无需担心:当且仅当 A == B 时,A 和 B 具有相同的内在哈希值。
  • 啊,明白了,谢谢!要挑选k 不同的种子,运行scala.util.Random.nextInt() k 不同时间是否有效,还是我需要做其他事情?
  • @grautur - 应该没问题。如果您希望您的代码是确定性的(尽管是伪随机的),以便每次都得到相同的答案,您需要使用您选择的种子创建一个新的 scala.util.Random。否则默认的nextInt 是一个足够好的随机数生成器。
  • @RexKerr 我认为不可能在新的MurmurHash3 实现中更改种子。
【解决方案2】:

可能最简单的方法是采用一些加密哈希函数并用不同的字节序列“播种”它。对于大多数实际目的,结果应该是独立的,因为这是加密散列函数应该具有的关键属性之一(如果替换消息的任何部分,散列应该完全不同)。

我会这样做:

// for each 0 <= i < k generate a sequence of random numbers
val randomSeeds: Array[Array[Byte]] = ... ; // initialize by random sequences

def hash(i: Int, value: Array[Byte]): Array[Byte] = {
    val dg = java.security.MessageDigest.getInstance("SHA-1");
    // "seed" the digest by a random value based on the index
    dg.update(randomSeeds(i));
    return dg.digest(value);
    // if you need integer hash values, just take 4 bytes
    // of the result and convert them to an int
}

编辑: 我不知道 Count-Min Sketch 的确切要求,也许一个简单的 has 函数就足够了,但这似乎不是最简单的解决方案。

我建议使用加密散列函数,因为你有很强的保证,生成的散列函数会非常不同,而且很容易实现,只需使用标准库即可。

另一方面,如果您有f1(x) = ax + b (mod p)f2(x) = cx + d (mod p) 形式的两个哈希函数,那么您可以使用一个简单的线性公式f2(x) = c / a * (f1(x) - b) + d (mod p) 使用另一个(不知道x)计算一个,这表明他们不是很独立。所以你可能会在这里遇到意想不到的问题。

【讨论】:

  • 在创建 Bloom 过滤器或 Count-Min Sketch 之类的东西时,使用加密哈希函数(与 f(x) = ax + b mod p 相反)有什么好处吗? AFAICT,加密哈希函数似乎有点矫枉过正,因为我不需要加密属性,但我可能会遗漏一些东西。
  • @grautur - ax+b mod p 有一种陷入循环的方式,这可能会在您的采样中创建可能有问题的模式,具体取决于您的采样假设。然后,如果您不想要完整的范围,您会遇到高阶与低阶位等问题。这对于有点随意加扰很有好处,但有相当快的替代方案效果更好。跨度>
猜你喜欢
  • 2018-03-09
  • 2013-04-23
  • 2018-12-29
  • 1970-01-01
  • 2013-12-26
  • 1970-01-01
  • 2018-04-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多