[论文笔记]multi-copy-cuckoo


事实上写的时候完全没想到会这么长,反而有点不想看orz
如何在500w个单词中统计特定前缀的单词有多少个?
如何判断一个数是否在40亿个整数中?

Introduction

chaining method和线性探查需要额外的时间和资源来解决冲突,达不到最佳的插入和查找性能bound。
Cuckoo hashing使用d个hash函数给每个item提供备用的桶,核心两个词:multiple hashing 和 relocation,帮助该算法实现很高的load ratio,在最坏的情况下最多要查找d个buckets去找某个item(O(1))。由于优秀的查找性能,经常被用在存储系统、数据库、privacy & security, 网络、架构、数据处理。
但是良好的查找性能是以插入复杂的冲突处理为代价的。多次重插后也可能还是失败。

对传统Cuckoo hashing着手改进的三个点

总体来说有三个因素影响了Cuckoo hashing的性能:

  • 插入时的循环踢出。由于标准Cuckoo hashing不能预测哪个item有空的备用buckets,只能通过BFS或者是随机的方式去决策。会浪费时间不说,还可能造成死循环。A good strategy should find a solution fast if such solution exists
  • 插入失败的损耗要尽可能小。传统的cuckoo hashing会rehash,把所有插入的读出来,重新算一个hash函数,然后再放入一个更大的表。一个更靠谱的补救措施是分配一个额外的小空间存所有插入失败的items。但是如果在主表里没有查找到,还是要到stash里面再找。额外的查找不仅影响查找项目,能使也限制了主表的最大可承载数。要最大化地利用stash,必须减少在stash中查找的消耗,提高可扩展性以及减少没必要的checking
  • 一个循环中多桶检查:查找一个item的时候,所有的备用桶都需要访问,影响了查找性能,尤其在表很大,需要把表放在外部内存的情况下。narrow down the subset of buckets that may contain the item beforehand and optimize the accessing pattern

已有的方法是怎么改进的

maxloop 防止死循环。
  • 尝试预先判断出循环次数,从一开始就不允许进入死循环:SmartCuckoo[15]、Necklace[16]
  • 减少踢出过程中的重复部分,使得更多的buckets被搜索到,搜索到空桶的概率也会增加:MinCounter[17]
  • 每个桶分配多个槽:blocked Cuckoo hash tables(BCHT)[18][19][20][21]
插入失败
  • 将stash on-chip?减少对性能的影响,当stash本身满的时候,其中的items会尝试插入主表When the stash itself is full, items stored in it will take a try to the main table until some space is freed. A small stash of size 4 is regarded as enough to achieve rather high load (for example 95% in [24]) with high probability.?:Cuckoo hashing with a stash (CHS)[22] propose
    已经很高了,好奇如何提升emm
多桶查询

当实施的平台上要用很小很快的on-chip memory去处理很大的表,(for example the ASIC/FPGA/SOC based packet processing devices).每次要检查多个位置就会成为大问题。

  • 使用可以放在on-chip内存里的compact helping structure例如 bloom filter来pre-screening,来减少不必要的对主表的访问:DEHT[25],EMOMA[24]

本文的方案

  • multiple copies of item,将item同时放入所有可用桶中。不用随机选择一个可用桶插入 通过冗余度可以很清楚地知道冲突的时候替换谁是最优方案,加速了插入速度,也避免了死循环。Keeping copies in all the available candidate buckets will maintain the flexibility and avoid entering the sub-optimal situation early: the optimal placement will come out naturally later on when the other occupied buckets are appropriately given away as per request to new items, who turn out to be the better owners of these buckets in an overall optimal arrangement.
  • 每个桶设置了一个计数器来跟踪存储的item有多少个备份。只要备份数大于1,必要的时候就可以被overwritten。同一个item的所有bucket的计数器值都一样。
  • 查找的时候,由于同一个item的所有桶的计数器应该一样,这个特点可以被用于排查掉不可能的情况。比如其中一个桶的c值是0,那么该item一定不存在。Furthermore, because an item can always overwrite a redundant copy to settle down, if a lookup fails with any candidate bucket having counter value larger than 1, we know that item must have not been inserted before and skip checking the stash. These 通过这些观察,可以避免查询一些bucket,或者是对stash的不必要检查。
  • McCuckoo特别适合于主表只能放在慢一点的二级存储上,上述三个问题可以被统一解决。为了最大化counters的好处,要把它们放在on-chip embedded memory. a compact on-chip counter array。操作逻辑也很简单。

本文的贡献:

  • 引入了multi-copy到Cuckoo-based hashing中,减少了relocation的盲目性,提升了bucket的可用性,以及提高了插入速度和正确率
  • 提出一种新的compact on-chip helping structure减少对off-chip memory的不必要访问
  • 一种有效的pre-screening机制减少对stash的查询

关于hash

rehash

当使用二度哈希时,重要的是在执行了 hashsize 次探查后,哈希表中的每一个位置都有且只有一次被访问到。也就是说,对于给定的 key,对哈希表中的同一位置不会同时使用 Hi 和 Hj。在 Hashtable 类中使用二度哈希公式,其始终保持 (1 + (((GetHash(key) >> 5) + 1) % (hashsize – 1)) 与 hashsize 互为素数(两数互为素数表示两者没有共同的质因子)。
向 Hashtable 中添加新元素时,需要检查以保证元素与空间大小的比例不会超过最大比例。如果超过了,哈希表空间将被扩充。

步骤如下:

  • 哈希表的位置空间几乎被翻倍。准确地说,位置空间值从当前的素数值增加到下一个最大的素数值。
  • 因为二度哈希时,哈希表中的所有元素值将依赖于哈希表的位置空间值,所以表中所有值也需要重新二度哈希

由此看出,对哈希表的扩充将是以性能损耗为代价。因此,我们应该预先估计哈希表中最有可能容纳的元素数量,在初始化哈希表时给予合适的值进行构造,以避免不必要的扩充。

chaining

在这里插入图片描述
使用链接技术添加元素的操作涉及到哈希计算和链表操作,但其仍为常量,渐进时间为 O(1)。而进行查询和删除操作时,其平均时间取决于元素的数量和桶(bucket)的数量。具体的说就是运行时间为 O(n/m),这里 n 为元素的总数量,m 是桶的数量。但通常对哈希表的实现几乎总是使 n = O(m),也就是说,元素的总数绝不会超过桶的总数,所以 O(n/m) 也变成了常量 O(1)。

cuckoo

Cuckoo hash算法分析——其根本思想和bloom filter一致 增加hash函数来解决碰撞 节省了空间但代价是查找次数增加

 基本思想:

cuckoo hash是一种解决hash冲突的方法,其目的是使用简单的hash 函数来提高hash table的利用率,同时保证O(1)的查询时间

基本思想是使用2个hash函数来处理碰撞,从而每个key都对应到2个位置。

插入操作如下:

1. 对key值hash,生成两个hash key值,hashk1和 hashk2, 如果对应的两个位置上有一个为空,那么直接把key插入即可。

2. 否则,任选一个位置,把key值插入,把已经在那个位置的key值踢出来。

3. 被踢出来的key值,需要重新插入,直到没有key被踢出为止。

 

我们先来看看cuckoo hashing有什么特点,它的哈希函数是成对的(具体的实现可以根据需求设计),每一个元素都是两个,分别映射到两个位置,一个是记录的位置,另一个是 备用位置。这个备用位置是处理碰撞时用的,这就要说到cuckoo这个名词的典故了,中文名叫布谷鸟,这种鸟有一种即狡猾又贪婪的习性,它不肯自己筑巢, 而是把蛋下到别的鸟巢里,而且它的幼鸟又会比别的鸟早出生,布谷幼鸟天生有一种残忍的动作,幼鸟会拼命把未出生的其它鸟蛋挤出窝巢,今后以便独享“养父 母”的食物。借助生物学上这一典故,cuckoo hashing处理碰撞的方法,就是把原来占用位置的这个元素踢走,不过被踢出去的元素还要比鸟蛋幸运,因为它还有一个备用位置可以安置,如果备用位置上 还有人,再把它踢走,如此往复。直到被踢的次数达到一个上限,才确认哈希表已满,并执行rehash操作。如下图所示(图片来源):

cuckoo_preview

 

我们不禁要问发生哈希碰撞之前的空间利用率是多少呢?不幸地告诉你,一维数组的哈希表上跟其它哈希函数没什么区别,也就50%而已。但如果是二维的呢?

一个改进的哈希表如下图所示,每个桶(bucket)有4路槽位(slot)。当哈希函数映射到同一个bucket中,在其它三路slot未被填满 之前,是不会有元素被踢的,这大大缓冲了碰撞的几率。笔者自己的简单实现上测过,采用二维哈希表(4路slot)大约80%的占用率(CMU论文数据据说 达到90%以上,应该是扩大了slot关联数

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值