2011-05-12 71 views
15

優化我有一個哈希表,其中在運行時,絕大多數的訪問遵循以下模式之一:哈希表的完整的迭代+鍵更換

  • 迭代通過所有鍵/值對。 (這個操作的速度很關鍵。)
  • 修改鍵(即刪除一個鍵/值對&添加另一個具有相同的值,但不同的鍵。檢測重複鍵&結合值,如有必要)。這是在一個循環,影響成千上萬的密鑰,但沒有其他操作干預。

我也希望它消耗盡可能少的內存。

其他標準操作必須可用,儘管它們使用較少,例如,

  • 插入一個新的鍵/值對
  • 給定一個鍵,查找相應的值
  • 變化與現有的關鍵

當然所有的「標準」哈希表相關聯的值包括大多數高級語言的標準庫在內的實現具有所有這些功能。我正在尋找的是爲第一個列表中的操作優化的實現。

與常見的實現問題:

  • 大多數哈希表實現使用分離鏈這工作,但我希望的東西,有更好的地方佔用的內存更少(即,每個桶的鏈接列表。)參考。注意:我的密鑰很小(每個13個字節,填充爲16個字節)。
  • 大多數開放尋址方案對我的應用程序有一個主要缺點:密鑰被刪除並在大型組中被替換。這留下了增加載入因子的刪除標記,需要經常重建表格。

方案即工作,但低於理想:每桶

  • 分離鏈與陣列(而不是一個鏈表):
    的參考普爾局部性,從內存碎片導致因爲小陣列被多次重新分配
  • 線性探測/二次哈希/雙哈希(有或沒有布倫特變化):
    錶快速填充刪除標記
  • 杜鵑散列
    只適用於< 50%的加載因子,我想要一個高LF來節省內存並加速迭代。

是否有專門的散列方案可以很好地適用於這種情況?


注:我有一個很好的哈希函數,既素表大小的功率爲2的和行之有效的,可用於雙散列,所以這不應該是一個問題。

+0

你似乎做了大量的研究,所以我沒有一個真正的答案。然而,我確實質疑你的參考地點的目標。當然,這取決於你的表的大小和你的實現語言,但我的經驗是,你只能保持哈希數組緩存(然後只有當你幸運)。對你來說,它可能有一個包含鍵和指向該值的指針的結構數組;即每個20字節,或2MB緩存約100,000個條目。當然,你需要一種能夠給你佈局控制的語言。而且負載因數相對較低。 – Anon 2011-05-12 18:46:48

+0

如果你確實擁有一個足夠容納整個表的緩存,它不會真的傷害你(太多),因爲沒有指針的散列數組,而是在第二個連續的內存塊中使用鏈表免費列表來恢復已刪除的條目)。 – Anon 2011-05-12 18:53:46

+0

您希望在表中存儲多少個元素,以及您希望在每次批次密鑰更新操作期間修改多少個密鑰? – 2011-05-13 03:51:20

回答

2

請問Extendable Hashing有幫助嗎?通過走'目錄'迭代鍵雖然應該很快。不知道該方案的「修改鍵值」操作是否更好。

1

根據你如何訪問數據,是否真的有意義使用哈希表呢?

由於您的主要用例涉及迭代 - 排序列表或btree可能是更好的數據結構。

它似乎並不像你真的需要恆定的時間隨機數據訪問哈希表是建立。

+0

更新仍然需要進行常量訪問。我已經嘗試了一個排序列表(劃分爲排序和未排序的區域)。缺點是必須定期合併區域,鎖定更新線程。 – finnw 2011-05-13 09:21:09

+1

我仍然建議嘗試一種基於樹的解決方案,然後 - btree或紅黑樹會保持查找/插入/刪除時間O(n),併爲您提供快速迭代 – TWK 2011-05-13 15:49:23

1

杜鵑散列法可以比50%的加載因子做得更好。

兩個哈希函數與四個項目將讓你超過90%,很少費力。請參閱本文:

http://www.ru.is/faculty/ulfar/CuckooHash.pdf

我使用的是杜鵑哈希並獲得好於99%的客座率有兩個散列函數和七項每桶建立預先計算的字典。