2012-03-04 4 views
10

Clojureにブルームフィルタを作成したいが、JVMベースの言語で利用できるすべてのハッシュライブラリについて多くの知識がない。クローゼットでブルームフィルタを構築するときに使用するハッシュテクニックは何ですか?

Clojureで最も速く(最も正確なものとは対照的に)ブルームマップの実装にはどのようなものを使用しますか?

+0

データのどのような種類のあなたの鍵ですか?文字列?バイト配列?整数? UUID? – pmdj

+0

私は文字列のセットに対してメンバシップをテストしています – jdoig

+1

文字列の 'hash()'メソッドによって報告された組み込みハッシュ値に、混合ハッシュ関数を繰り返し適用することができます。 http://www.cris.com/~Ttwang/tech/inthash.htm生成された値は相関が強すぎるため、ブルームフィルタを無効にする可能性があります。私が過去に使ってきたアプローチは、SHA-256のような非常に長い結果を持つハッシュ関数を使用し、その結果をチャンクに分割することです。これはあなたの目的には遅すぎるかもしれません。最も単純なのは、「文字列ハッシュ関数」のためのGoogle検索を行い、それが与える結果のいくつかを実装することかもしれません。 – pmdj

答えて

3

ブルームフィルタについての楽しいことは、効果的に動作するためには、複数のハッシュ関数が必要であるということです。

Java文字列には既に、 - String.hashCode()と32ビットの整数ハッシュを返す1つのハッシュ関数が組み込まれています。これはほとんどの目的でOKのハッシュコードです。これは十分である可能性があります。たとえば、これを2つの別々の16ビットハッシュコードに分割すると、ブルームフィルタが機能するのに十分です。あなたはおそらくいくつかの衝突を得るでしょうが、それはうまくいきます - ブルームフィルタはいくつかの衝突を持つと予想されます。

もしそうでない場合は、独自のロールを作成したい場合は、String.getChars()を使用して生のcharデータにアクセスし、複数のハッシュコードを計算することをお勧めします。

あなたは(単に文字の値を合計)始めるためにClojureのコード:

(let [s "Hello" 
     n (count s) 
     cs (char-array n)] 
    (.getChars s 0 n cs 0) 
    (areduce cs i v 0 (+ v (int (aget cs i))))) 
=> 500 

注GetCharsはを呼び出すためのClojureのJava相互運用機能を使用すると、あなたの上に非常に高速な繰り返しを与えるためにareduceの使用文字配列

Githubで見つかったJava Bloomフィルタの実装については、https://github.com/MagnusS/Java-BloomFilterをご覧ください。ハッシュコードの実装は一目瞭然ですが、バイト配列を使用しています。これは文字エンコーディングのオーバーヘッドを処理する必要があるため、charを使用するよりも少し効率が悪いと思います。

+1

Bloom FilterをJavaで書いたことがあります(質問はJVMとハッシングアルゴリズムに関するものでした)。複数のハッシュ関数は必要ありません。確かに(以下の答えを参照)、良いMumurHashはBloom Filtersには優れています。なぜなら、Bloom Filtersは非常に高速であり、Bloom Filtersは本質的に偽陽性率を持っているので、衝突の発生率はそれほど重要ではありません。パフォーマンスのベストプラクティスと偽陽性率の管理は、入力キーをハッシュしてビットセット分布を滑らかにするため、セット内のデータ型も関係ありません。 –

+0

@Darrell - 結果を複数のハッシュ関数に分割できるだけの独立した計算が必要です。それは以下の答えです - 私はそれを "複数のハッシュ関数を使う"と定義します:-) – mikera

+0

質問は「JVMベースの言語で利用可能なライブラリをハッシングする」というものでした。使用/計算されるハッシュバケットの数。私はフレーズ 'ハッシュ関数'は関数またはメソッド(実装)を意味すると考えていますが、以下のコメントでは '必要なハッシュ数を計算します。ご不便をおかけして申し訳ありませんが、うまくいけば、これはかなり重いコンピュータサイエンスの話題なので、これは新しいユーザーを明確にします。 –

11

Bloom Filterの実装をApache Cassandraに見てください。これは非常に高速のMurmurHash3アルゴリズムを使用し、異なる方法で2つのハッシュ(または同じハッシュの2つの部分をMurmurHash2の代わりにMurmurHash3にアップグレードした後)を組み合わせて、目的のハッシュ数を計算します。

組み合わせの生成方法は、this paper

に記載されており、ここではカサンドラのソースコードからの抜粋ですされています

long[] hash = MurmurHash.hash3_x64_128(b, b.position(), b.remaining(), 0L); 
    long hash1 = hash[0]; 
    long hash2 = hash[1]; 
    for (int i = 0; i < hashCount; ++i) 
    { 
     result[i] = Math.abs((hash1 + (long)i * hash2) % max); 
    } 

を参照してください

Bloomfilter and Cassandra = Why used and why hashed several times?

関連する問題