SlideShare une entreprise Scribd logo
1  sur  35
よくわかる
Hopscotch Hashing
          @kumagi
Locking!!!!
   このアルゴリズムは
Lock-freeではありません!
 Lock-freeを期待して見にきた方は回れ右!
Hashmapとは?
• みんな大好き連想配列!
 – RubyでもPerlでもPythonでも人気者!
 – C++でならunordered_map、JavaならHashMap
• 何かの値をキーとして別の値を保存・検索できるデータ構造
 – 「山!」→「川!」
• とにかく高速!
 – O(1)で動作するデータ構造
   • 大量のデータを入れても検索速度が変わらないただ一つのデータ
     構造
その仕組み
山!      8番目!



          川!




    Hash関数に通すだけで
保存or検索すべき場所が判明する!
欠点




混んでくるとぶつかる
ぶつかったら?


 広々!




大きなところへ
引っ越せばいい
でもそれは最後の手段
• Hash値が衝突するのはそんなに珍しくない
 – そのために配列確保しなおしてたら遅すぎる
 – メモリ効率悪すぎる


• メモリにやさしい解決方法が望まれている
その戦略
• 大きく分けて二つ




     Open              Closed
   Addressing        Addressing
                or
Closed Addressing




新しく作ってポインタで繋ぐ!
Closed Addressing
• 1つのアドレスにつき1つの場所(とそこからポインタで繋
  がった場所)にしか対象の物が置かれないからClosedと呼ば
  れる
• ポインタで繋がるリスト構造から「チェインハッシュ」とも
  呼ばれる
• 利点
 – チェインの長さにだけ気をつければO(1)の速度を保てる
 – ポインタを繋ぎ換えればLinearHashなどが作れるし簡単
• 欠点
 – ポインタを辿るのが遅い
対するOpen Addressingは…
Open Addressing

          やったね!




    隣を使う!
選べる探索バリエーション(併用不
       可)
                        Liner Probing




                        Quadratic Probing
     ±1, 2, 4, 8, 16…



                        Double Hashing
             ±Hash(x)
Open Addressing
• 一つのHash値に対して配列上の複数の場所が該当しうるの
  でOpenと名がつくんだと思う
• 利点
 – キャッシュの局所性を生かせるので速い(特にLinear Probing)
 – ポインタの分だけ省メモリ
• 欠点
 – 削除時にはデータを消さずに削除フラグを立てて再利用させる
   だけ
   • データが存在している事そのものが「まだ配列の続きにあるかも
     よ」という状態を表しているので完全に消しちゃうとマズい
   • よって挿入・削除で密度が上がってくると入ってるデータが少な
     い時でも検索・挿入・削除の性能がガタ落ちする
ベンチマーク比較
             キ
             ャ
             ッ
             シ
             ュ
             ミ
             ス
             頻
             度




 使用済み要素の割合
Cuckoo Hashing
• 鳥のカッコウの習性のように、托卵する際に他の鳥の卵が
  あった場合に退けるハッシュマップ
 – OpenAddressingにもClosedAddressingにも分類しがたい
• 2つの配列と2つのハッシュ関数を用意する
• きちんと作れば頑健で高信頼
 – 詳しくはクヌース先生のTAoCP本を。
Cuckoo Hashing
• 2つの配列に2つのハッシュ関数。1つのアイテムは2つの配列
  のうちどちらかに入っていれば良い。
• 衝突時には
  もう一つの配列を使う               Hash1(y)
                  Hash1(x)
• 両方埋まってたら
既存のをもう一つの配列へ    Hash2(x)     Hash2(y)
• それも埋まって
たらその片方をもう一つの配列へ(以後再帰的に全部
• 検索はいつも2つの配列を2つのハッシュ関数で探すだけ
• 利点
       Cuckoo Hashing
 – 検索は2つの配列の一箇所ずつを探すだけなので高速
 – 多少ハッシュ値が偏ってももう一つのハッシュ値が散れば問題
   ない
• 欠点
 – 密度に応じて挿入のコストが上がる
 – 2つの配列を使う分メモリを食う
   • チェインのポインタを持たなくてよいのでそんなに問題でないか
     も
 – 特性上、全体の半分が埋まったところで性能がガタ落ちする
   • タチが悪いと円環して終わらない事もあり得るのかな
 – つまり半分埋まる前に拡大する必要がある
   • スッカスカのテーブルを維持しなきゃいけないからありがたみ少
     ない
そこでHopscotch!



OpenAddressingのLinearProbingのキャッシュヒット
     力とOpenAddressingの検索力を両立する
   新しいOpenAddressingなハッシュテーブル!
What is Hopscotch?
         いわゆる「けんけんぱ」
         飛び方を決めてその通りに
         飛ぶ遊び
         名前かっこいい!
データ構造
• 配列上の全バケットがデータの他にHop情報を持つ。
 – Hop情報は物理的には1ワード幅のビット列
   • 図では大きさの都合上8bitということに
 – ここから隣のどのバケットに、本来ここに入るべきだったアイ
   テムが置かれているかを示す。
              1word
          アイテム   11001010   1なら対応データ有り
                            0なら
検索
• 普通のHashmapと同様にバケットを検索する
• そのバケットのHop情報を見て、このバケット位置に対応する
  データを順番に調べていき目的のものを見つける
• 1wordのbit数分の比較を行えば検索の成功or失敗を決定できる
   – 比較回数はO(1)で済む
          アイテム   11001010


                   12   3   4

            4つbitが立っていたので比較4
            回
検索
• チェインハッシュで言うところのこれと状態は同じ
 – 一つのバケット位置の下に複数のアイテムがぶら下がる
 – 配列に連続している分、左のHopscotchのほうがキャッシュ
   ヒット率が高い


      1   アイテム        アイテム   11001010
      2   アイテム

      3   アイテム                 12   3   4

      4   アイテム
挿入
• およそ8ワード分のビット数先のバケットまで配列を舐めな
  がら、アイテムが入っていない空バケットが無いかを探す
 – 無いならテーブルを拡張して全部再配置してやり直し

                       アイテム   11010100
     アイテム   11001010


ここに入れたいけ
 ど空きが無い
                       ビッシ
                       リ
挿入
• およそ8ワード分のビット数先のバケットまで配列を舐めな
  がら、アイテムが入っていない空バケットが無いかを探す
 – 空バケットとはHop情報部分はともかくアイテム部分が空の物




              8word bit先まで空きを探
              す
ここに入れたいけ
 ど空きが無い
               ビッシ
               リ
挿入
• およそ8ワード分のビット数先のバケットまで配列を舐めな
  がら、アイテムが入っていない空バケットが無いかを探す
 – 空バケットとはHop情報部分はともかくアイテム部分が空の物

                        空バケットあっ
                          た!
              8word bit先まで空きを探
              す
ここに入れたいけ
 ど空きが無い
               ビッシ
               リ
挿入
• およそ8ワード分のビット数先のバケットまで配列を舐めな
  がら、アイテムが入っていない空バケットが無いかを探す
 – 空バケットとはHop情報部分はともかくアイテム部分が空の物
• 空バケットをswapしながら左に移動させていく
 – バケットからHop情報で飛べる1wordビット範囲でしかswapは
   しない                  アイテム
                           01010100


ここに入れたいけ
 ど空きが無い
                 ビッシ
                 リ         swap
挿入
• およそ8ワード分のビット数先のバケットまで配列を舐めな
  がら、アイテムが入っていない空バケットが無いかを探す
 – 空バケットとはHop情報部分はともかくアイテム部分が空の物
• 空バケットをswapしながら左に移動させていく
 – バケットからHop情報で飛べる1wordビット範囲でしかswapは
   しない                  アイテム
                           00010110


ここに入れたいけ
 ど空きが無い
                 ビッシ
                 リ         swap完了
挿入
• およそ8ワード分のビット数先のバケットまで配列を舐めな
  がら、アイテムが入っていない空バケットが無いかを探す
 – 空バケットとはHop情報部分はともかくアイテム部分が空の物
• 空バケットをswapしながら左に移動させていく
 – バケットからHop情報で飛べる1wordビット範囲でしかswapは
   しない
• 挿入したい位置から1word幅になるまで続ける
 ここに入れたいけ
  ど空きが無い
                 ビッシ
                 リ   swap
挿入
• およそ8ワード分のビット数先のバケットまで配列を舐めな
  がら、アイテムが入っていない空バケットが無いかを探す
 – 空バケットとはHop情報部分はともかくアイテム部分が空の物
• 空バケットをswapしながら左に移動させていく
 – バケットからHop情報で飛べる1wordビット範囲でしかswapは
   しない
• 挿入したい位置から1word幅になるまで続ける
 ここに入れたいけ
  ど空きが無い
                 ビッシ
                 リ   swap完了
挿入
• これで空き部分に挿入できる
挿入
• これで空き部分に挿入できる
• アイテムを書き込んでHop情報を更新して完了



          アイテム   11001011
削除
• 普通に検索して該当するアイテムを消去してHop情報のbitを落と
  すだけ




          アイテム   11001010
削除
• 普通に検索して該当するアイテムを消去してHop情報のbitを落と
  すだけ
 – 超簡単




          アイテム   11000010
ポイント
• バケットそれぞれにアイテムとHop情報が入っている。
  – Hash値を算出して配列の該当部分にアクセスした瞬間に、その
    周辺もキャッシュラインに同時に載るためキャッシュミスが減
    る
• 検索時は必ずそのバケットから1wordのbit数以内の距離にあ
  る
  – カッコウハッシュはバケット2つしか1つのアイテムが入りうる
    候補が無かったのに対して、1word幅bit個まで候補が増えてい
    る
     • 配列を拡張しなくても入る量が多い
• そんなわけで実装してみた。Boost::unordered_mapより速
  い。
  – https://gist.github.com/2943289

Contenu connexe

Tendances

プログラミングコンテストでのデータ構造
プログラミングコンテストでのデータ構造プログラミングコンテストでのデータ構造
プログラミングコンテストでのデータ構造
Takuya Akiba
 
勉強か?趣味か?人生か?―プログラミングコンテストとは
勉強か?趣味か?人生か?―プログラミングコンテストとは勉強か?趣味か?人生か?―プログラミングコンテストとは
勉強か?趣味か?人生か?―プログラミングコンテストとは
Takuya Akiba
 

Tendances (20)

Linuxにて複数のコマンドを並列実行(同時実行数の制限付き)
Linuxにて複数のコマンドを並列実行(同時実行数の制限付き)Linuxにて複数のコマンドを並列実行(同時実行数の制限付き)
Linuxにて複数のコマンドを並列実行(同時実行数の制限付き)
 
Re永続データ構造が分からない人のためのスライド
Re永続データ構造が分からない人のためのスライドRe永続データ構造が分からない人のためのスライド
Re永続データ構造が分からない人のためのスライド
 
キャッシュコヒーレントに囚われない並列カウンタ達
キャッシュコヒーレントに囚われない並列カウンタ達キャッシュコヒーレントに囚われない並列カウンタ達
キャッシュコヒーレントに囚われない並列カウンタ達
 
プログラムを高速化する話
プログラムを高速化する話プログラムを高速化する話
プログラムを高速化する話
 
直交領域探索
直交領域探索直交領域探索
直交領域探索
 
プログラミングコンテストでのデータ構造 2 ~動的木編~
プログラミングコンテストでのデータ構造 2 ~動的木編~プログラミングコンテストでのデータ構造 2 ~動的木編~
プログラミングコンテストでのデータ構造 2 ~動的木編~
 
プログラミングコンテストでのデータ構造
プログラミングコンテストでのデータ構造プログラミングコンテストでのデータ構造
プログラミングコンテストでのデータ構造
 
Glibc malloc internal
Glibc malloc internalGlibc malloc internal
Glibc malloc internal
 
双対性
双対性双対性
双対性
 
ウェーブレット木の世界
ウェーブレット木の世界ウェーブレット木の世界
ウェーブレット木の世界
 
Master Canary Forging: 新しいスタックカナリア回避手法の提案 by 小池 悠生 - CODE BLUE 2015
Master Canary Forging: 新しいスタックカナリア回避手法の提案 by 小池 悠生 - CODE BLUE 2015Master Canary Forging: 新しいスタックカナリア回避手法の提案 by 小池 悠生 - CODE BLUE 2015
Master Canary Forging: 新しいスタックカナリア回避手法の提案 by 小池 悠生 - CODE BLUE 2015
 
できる!並列・並行プログラミング
できる!並列・並行プログラミングできる!並列・並行プログラミング
できる!並列・並行プログラミング
 
勉強か?趣味か?人生か?―プログラミングコンテストとは
勉強か?趣味か?人生か?―プログラミングコンテストとは勉強か?趣味か?人生か?―プログラミングコンテストとは
勉強か?趣味か?人生か?―プログラミングコンテストとは
 
Rustに触れて私のPythonはどう変わったか
Rustに触れて私のPythonはどう変わったかRustに触れて私のPythonはどう変わったか
Rustに触れて私のPythonはどう変わったか
 
B-link-tree
B-link-treeB-link-tree
B-link-tree
 
lsh
lshlsh
lsh
 
[GTCJ2018]CuPy -NumPy互換GPUライブラリによるPythonでの高速計算- PFN奥田遼介
[GTCJ2018]CuPy -NumPy互換GPUライブラリによるPythonでの高速計算- PFN奥田遼介[GTCJ2018]CuPy -NumPy互換GPUライブラリによるPythonでの高速計算- PFN奥田遼介
[GTCJ2018]CuPy -NumPy互換GPUライブラリによるPythonでの高速計算- PFN奥田遼介
 
【DL輪読会】Hyena Hierarchy: Towards Larger Convolutional Language Models
【DL輪読会】Hyena Hierarchy: Towards Larger Convolutional Language Models【DL輪読会】Hyena Hierarchy: Towards Larger Convolutional Language Models
【DL輪読会】Hyena Hierarchy: Towards Larger Convolutional Language Models
 
色々なダイクストラ高速化
色々なダイクストラ高速化色々なダイクストラ高速化
色々なダイクストラ高速化
 
Tensorflow Liteの量子化アーキテクチャ
Tensorflow Liteの量子化アーキテクチャTensorflow Liteの量子化アーキテクチャ
Tensorflow Liteの量子化アーキテクチャ
 

En vedette

冬のLock free祭り safe
冬のLock free祭り safe冬のLock free祭り safe
冬のLock free祭り safe
Kumazaki Hiroki
 
What is jubatus? How it works for you?
What is jubatus? How it works for you?What is jubatus? How it works for you?
What is jubatus? How it works for you?
Kumazaki Hiroki
 

En vedette (14)

SkipGraph
SkipGraphSkipGraph
SkipGraph
 
冬のLock free祭り safe
冬のLock free祭り safe冬のLock free祭り safe
冬のLock free祭り safe
 
トランザクションの設計と進化
トランザクションの設計と進化トランザクションの設計と進化
トランザクションの設計と進化
 
Lockfree Priority Queue
Lockfree Priority QueueLockfree Priority Queue
Lockfree Priority Queue
 
Cache obliviousの話
Cache obliviousの話Cache obliviousの話
Cache obliviousの話
 
What is jubatus (short)
What is jubatus (short)What is jubatus (short)
What is jubatus (short)
 
Lockfree list
Lockfree listLockfree list
Lockfree list
 
Lockfree Queue
Lockfree QueueLockfree Queue
Lockfree Queue
 
What is jubatus? How it works for you?
What is jubatus? How it works for you?What is jubatus? How it works for you?
What is jubatus? How it works for you?
 
トランザクション入門
トランザクション入門 トランザクション入門
トランザクション入門
 
Bloom filter
Bloom filterBloom filter
Bloom filter
 
地理分散DBについて
地理分散DBについて地理分散DBについて
地理分散DBについて
 
分散システムについて語らせてくれ
分散システムについて語らせてくれ分散システムについて語らせてくれ
分散システムについて語らせてくれ
 
本当は恐ろしい分散システムの話
本当は恐ろしい分散システムの話本当は恐ろしい分散システムの話
本当は恐ろしい分散システムの話
 

よくわかるHopscotch hashing