繁体   English   中英

将16位整数哈希有效地哈希到256位空间

[英]Hash 16-bit integer to a 256-bit space efficiently

听起来越来越很奇怪,但这就是我想要做的。 我想采用16位整数的整个序列,并对每个哈希进行哈希处理,以使其均匀地映射到256位空间。

原因是我试图将16位数字空间的一部分放入256位Bloom过滤器中,以进行快速成员资格测试。

我可以在每个整数上使用一些众所周知的哈希函数,但是我正在寻找一种非常高效的实现(只需几条指令),以便在GPU着色器程序中很好地运行。 我感觉这样的事实:已知哈希输入只有16位,可以以某种方式通知哈希函数,但是我看不到解决方案。

有任何想法吗?


EDITS

根据答复,我的原始问题令人困惑。 对于那个很抱歉。 我将尝试使用更具体的示例来重述它:

我有一个来自集合S的n个数字的子集S1,其范围为(0,2 ^ 16-1)。 我需要用一个由单个哈希函数构造的256位Bloom过滤器来表示此子集S1。 使用布隆过滤器的原因是出于空间考虑。 我选择了一个256位的布隆过滤器,因为它符合我的空间要求,并且误报的可能性很低。 我正在寻找一个非常简单的哈希函数,该函数可以从集合S中获取一个数字,并以256位表示该数字,从而使每个位具有大约为1或0的概率。

哈希函数要求简单的原因是,此哈希函数将不得不在每个像素上运行数千次,因此在任何我可以修整指令的地方都是一个胜利。

我相信所提出的问题有些混乱。 我将首先尝试清除我在上面注意到的所有不一致之处。

OP最初表示,他正在尝试将较小的空间映射到较大的空间。 如果确实如此,则不需要使用布隆过滤器算法。 相反,如上面的注释中所建议的,标识功能是设置和测试每个位所必需的唯一“哈希”功能。 但是,我断言这不是OP真正想要的。 如果是这样,那么OP必须在内存中存储2^256位(基于问题的表达方式),以使16位整数(即2^16 )的空间小于其设置的大小; 这将占用不合理的内存量,并且不太可能是这种情况。

因此,我假设问题约束如下:我们有一个256位的位向量 ,我们要在其中映射16位整数的空间。 也就是说,我们有256位可用于映射2^16可能的不同整数。 因此,我们实际上并没有映射到更大的空间,而是映射到了更小的空间。 类似地,确实出现了(再次如前面的注释中先前指出的那样)OP正在请求单个哈希函数。 在这种情况下,对于布隆过滤器的工作原理存在明显的误解。

布隆过滤器通常使用一组独立于哈希的哈希函数来减少误报。 无需赘述,布隆过滤器的每个输入都通过所有n哈希函数运行,然后针对每个函数测试位向量中的所得索引。 如果将所有测试的索引都设置为1 ,则该值可能在集合中(如果所有n散列函数存在适当的冲突或重叠,则会出现误报)。 此外,如果将任何索引设置为0 ,则该值绝对不在集合中。 考虑到这一点,重要的是要注意完全饱和的布隆过滤器没有任何好处。 也就是说,对布隆过滤器的每个查询都将返回该项目在集合中。

哈希函数问题

现在,回到OP的原始问题。 最好使用已知的哈希算法(因为这些算法在数学上很难编写,并且“滚动自己的算法”通常效果不佳)。 如果您担心效率低至时钟周期,请使用适合您的体系结构的汇编语言自己实现算法,以减少每个哈希函数的运行时间。 请记住,从算法上讲,哈希函数应在O(1)时间内运行,因此,如果正确实现,则它们不应造成太多开销。 首先,我建议您考虑修改后的伯恩斯坦哈希。 我在下面针对您的特定情况编写了一个版本(主要出于示例目的):

unsigned char modified_bernstein(short key)
{
  unsigned ret = key & 0xff;
  ret = 33 *  ret ^ (key >> 8);
  return ret % 256; // Try to do some modulo math to keep it in range
}

我改编的伯恩斯坦方法通常根据输入的字节数运行。 由于short类型是2个字节或16-bits ,因此我从算法中删除了所有变量和循环,并简单地执行了一些小操作以获取每个字节。 最后, unsigned char可以返回[0,256)范围内的值,这迫使哈希函数返回位向量中的有效索引。

如果你乘(使用uint32_t )由总理(或与此有关的任何奇数)一个16位的值, p 2 ^ 31和2 ^ 32之间,那么“可能”抹黑结果整个32位空间相当均匀。 然后,您可能想要添加另一个素数,以防止0映射到0 (您希望每一位具有相等的概率为01 ,因此2 ^ 256中只有一个输入值应该输出全零,并且由于存在仅2 ^ 16个输入,这意味着您不希望它们输出全零)。

因此,这就是通过一次操作将16位扩展为32位的方法(以及加载常量所需的任何指令)。 使用四个不同的值p1 ... p4获得256位,并使用不同的p值运行一些测试以找到好的值(即,在给定的p大小的情况下,产生的误报不会比您对Bloom过滤器的期望多得多)设置您要进行编码并假设使用理想的哈希函数)。 例如,我很确定-1是一个错误的p值。

但是,无论这些值多么好,您都会看到一些相关性:例如,正如我在上面所描述的那样,所有4个单独值的最低位都相等,这是一个非常严重的依赖性。 因此,您可能希望进行更多“混合”操作。 例如,您可能会说最终输出的每个字节应该是我所描述的两个字节的XOR(而不是两个最小公称字节!),只是为了摆脱简单的算术关系。

但是,除非我误解了这个问题,否则布鲁姆过滤器通常不会工作 通常,您希望您的哈希为每个输入生成确切固定数量的设置位,并且所有计算误报率的算法都依赖于此。 这就是为什么对于256位大小的Bloom过滤器,您通常会有k 8位哈希,而不是一个256位哈希。 k通常小于以位为单位的过滤器大小的一半(最佳值是过滤器中每个值的位数,乘以ln(2) ,约为0.7)。 因此,通常您希望每个位为1的概率高达0.5。

原因是,一旦您对至少4个此类256位值进行“或”运算,就几乎设置了过滤器中的所有位(其中16位中的15位)。 因此,您已经发现了很多误报。

但是,如果您已经完成数学运算,并且对单个散列函数感到满意,那么该哈希函数会产生可变数量的平均置位位数,那么就足够了。 还是数字256的重复出现只是一个巧合,因为对于您选择的设置大小, k恰好是32,并且您实际上将256位哈希用作32个8位哈希?

[编辑:您的评论澄清了这一点,但是无论如何k都不会太高,以至于您总共需要256位哈希。 显然,在这种情况下,使用具有每个值超过16位(即少于16个值)的Bloom过滤器是没有意义的,因为使用相同数量的空间,您可以只列出这些值,并且误报率为0。每个值具有16位的filter的假阳性率大约为2200中的1。即使在那里,最优k也只有23,也就是说,您应该为集合中的每个值在filter中设置23位。 如果您希望这些集合大于16个值,那么您希望为每个元素设置更少的位,您将获得更高的误报率。]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM