Lite_stream
@Lite_stream

Seed для CRC32?

Контекст: решил написать хэш-таблицу без коллизий
Выбор пал между кукушкой и идеальным хешированием (двухуровневое хеширование в качестве реализации)
Выбрал 2-е (у кукушки мат. ожидание кеш миса 1.75, а у двухуровневого хеширования 1, если объекты небольшие)

В качестве хеш функции выбрал crc32-c (по советам разработчиков ClickHouse'а) - хорошее распределение хешей + высокая скорость (2 процессорных цикла, если использовать аппаратную реализацию _mm_crcX_uX, где X - количество бит)

Поскольку для подбора хеш функции без коллизий требуется её параметризировать, то в качестве параметра для crc32-c выбрал сам накопленный циклический код (1-й аргумент _mm_crcX_uX).

Собственно решил потестить за сколько в среднем попыток в зависимости от load factor'а бакета он заполнится без коллизий, меняя параметр (crc) хеш функции после каждой неудачи. Код

Вопрос: если в качестве параметра использовать обычный инкремент на каждой итерации (40-я закоменченная строка), то он никогда не покинет while(true), т.е. хеши при остатке от деления на 16 одинаковые для разных параметров. Но если в качестве crc взять хеш с предыдущей итерации (строка 25), то алгоритм сходится ~ за 5к попыток.
Чем можно объяснить такое поведение?
  • Вопрос задан
  • 297 просмотров
Пригласить эксперта
Ответы на вопрос 1
mayton2019
@mayton2019
Bigdata Engineer
Я сразу попробую ответить на главный вопрос.

написать хэш-таблицу без коллизий


Написать такую таблицу можно если мы заранее знаем весь набор данных (в случае автора это
множество ключей (K). Здесь для простоты предполагаем что ключи - это целые числа int32 (DWORD).

Алгоритм примерно такой:
1) Берем размер хеш-таблицы в n = size(K). Метод открытой адресации.
2) Берем любую хеш-функцию (по области определения больше чем n
SHA1, MD5, xxhash, mur-mur-hash)
3) Начинаем наполнять таблицу.
4) Как только детектирована коллизия - удаляем старую таблицу и создаем новую
с размером например 120% от исходного n.
5) Повторяем алгортм до тех пор пока не будут расставлены все ключи.

Profit.

Если мы не знаем наши данные изначально (у нас их нет и мы не знаем количество и тип данных)
то мы не можем гарантировать отсустствие коллизий хотя-бы потому что у нас
нету такой хеш функции которая бы гарантировала отсутствие коллизий на вариативном
типе данных
.

Изучать хеширование на базе целых чисел - вобщем-то не интересно. Более общий случай - это
строки (String) и я-бы делал эксперименты со строками и с реальными данными (мобильные
телефоны емейлы налоговые номера и прочее). Целые числа - это .... слишком синтетические
тесты и их результаты потом никуда натянуть нельзя.

UPD: Алгоритм в таком виде не работает. По крайней мере от коллизий мы не избавились.
Не голосуйте здесь пока.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы