Какие методы хеширования использовать при создании фильтра Блума в clojure?

Я хочу создать фильтр Блума в Clojure, но у меня мало знаний обо всех библиотеках хеширования, которые могут быть доступны для языков на основе JVM.

Что я должен использовать для самой быстрой (в отличие от самой точной) реализации карты цветения в Clojure?


person jdoig    schedule 04.03.2012    source источник
comment
К какому типу данных относятся ваши ключи? Струны? Байтовые массивы? Целые числа? UUID?   -  person pmdj    schedule 04.03.2012
comment
Я проверяю принадлежность к набору строк   -  person jdoig    schedule 04.03.2012
comment
Вы можете попробовать повторно применить смешанную хэш-функцию к встроенному хеш-значению, указанному методом hash() в строке, например. cris.com/~Ttwang/tech/inthash.htm Сгенерированные значения может слишком сильно коррелировать, что может сделать фильтр Блума неэффективным. Подход, который я использовал в прошлом, заключается в использовании хеш-функции с очень длинным результатом, например SHA-256, и разбиении результата на куски. Это может быть слишком медленным для ваших целей. Самым простым может быть просто поиск в Google «строковой хэш-функции» и реализация нескольких результатов, которые она дает.   -  person pmdj    schedule 04.03.2012


Ответы (2)


Самое интересное в фильтрах Блума заключается в том, что для эффективной работы им нужно несколько хеш-функций.

Строки Java уже имеют одну встроенную хэш-функцию, которую вы можете использовать — String.hashCode() with возвращает 32-битный целочисленный хэш. Это нормальный хэш-код для большинства целей, и, возможно, этого достаточно: например, если вы разделите его на 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

Обратите внимание на использование взаимодействия Java в Clojure для вызова getChars и использование areduce для очень быстрой итерации по массиву символов.

Вас также может заинтересовать эта реализация фильтра Блума Java, которую я нашел на Github: https://github.com/MagnusS/Java-BloomFilter . Реализация хеш-кода на первый взгляд выглядит нормально, но она использует массив байтов, который, как мне кажется, немного менее эффективен, чем использование символов, из-за необходимости иметь дело с накладными расходами кодирования символов.

person mikera    schedule 04.03.2012
comment
Написав фильтр Блума на Java (вопрос был о JVM и алгоритмах хеширования), несколько хеш-функций НЕ нужны. Действительно (см. ответ ниже), хороший MumurHash отлично подходит для фильтров Блума, потому что они чрезвычайно быстры, а незначительное увеличение числа столкновений на самом деле не является фактором, поскольку фильтры Блума в любом случае по своей природе имеют ложноположительный уровень. Тип данных в наборе также не имеет значения, поскольку наилучшая практика для повышения производительности и управления ложноположительными коэффициентами состоит в том, чтобы сгладить распределение битового набора путем хэширования входных ключей. - person Darrell Teague; 28.05.2013
comment
@Darrell - ну, вам нужно достаточно независимо вычисленных битов, чтобы вы могли сегментировать результат на несколько хеш-функций. Вот что делает ответ ниже - я бы определил это как использование нескольких хеш-функций :-) - person mikera; 29.05.2013
comment
Вопрос был о библиотеках хеширования, которые могут быть доступны для языков на основе JVM, поэтому комментарий относился к ним по сравнению с «количеством хэш-сегментов», которые используются/вычисляются. Я думаю, что фраза «хеш-функция» подразумевает функцию или метод (реализация), тогда как в комментарии ниже говорится «вычислить желаемое количество хэшей». Извините за некоторую путаницу, но, надеюсь, это прояснит для новых пользователей, поскольку это довольно тяжелая тема компьютерных наук. - person Darrell Teague; 31.05.2013

Взгляните на реализацию фильтра Блума в Apache Cassandra. Он использует очень быстрый алгоритм MurmurHash3 и объединяет два хэша (или две части один и тот же хэш, начиная с обновления до MurmurHash3 вместо MurmurHash2) разными способами вычислить нужное количество хэшей.

Комбинаторный подход к генерации описан в этой статье.

и вот фрагмент исходного кода Cassandra:

    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 и Cassandra = Почему используется и почему хэшируется несколько раз?

person DNA    schedule 04.03.2012