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к попыток.
Чем можно объяснить такое поведение?
  • Вопрос задан
  • 255 просмотров
Пригласить эксперта
Ответы на вопрос 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: Алгоритм в таком виде не работает. По крайней мере от коллизий мы не избавились.
Не голосуйте здесь пока.
Ответ написан
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы