Задать вопрос
  • Seed для CRC32?

    Lite_stream
    @Lite_stream Автор вопроса
    mayton2019, не понимаю, как оно за разумное время могло сработать при 5'000'000 в 5'008'333 слотов. Вот, например, рассмотрим момент, когда вставилось 2'500'000 ключей (т.е. load factor ~ 0.5) теперь осталось вставить ещё столько же ключей и для каждого вероятность, что он вызовет коллизию не меньше 0.5 (и она будет расти по мере продвижения), то есть после момента, как вставилось без коллизий 2.5кк ключей вероятность, что остальные вставятся без коллизий не меньше 0.5^2'500'000
  • Seed для CRC32?

    Lite_stream
    @Lite_stream Автор вопроса
    mayton2019, а какие ключи (равномерное распределение, нормальное распределение, инкрементальные значения и т.д.) ? какая хеш функция ? с какой попытки сошлось ?
  • Seed для CRC32?

    Lite_stream
    @Lite_stream Автор вопроса

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

    Такой подход, к сожалению, сходится к ~n^2 памяти


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

    А как же какой-нибудь Map(id, User) ))
  • Seed для CRC32?

    Lite_stream
    @Lite_stream Автор вопроса
    mayton2019, внешняя и все внутренние таблицы могут быть выделены в непрерывном куске памяти, только вот из-за того, что размер внутренней константный, перерасход памяти получается порядка 10-16n
  • Seed для CRC32?

    Lite_stream
    @Lite_stream Автор вопроса
    mayton2019, читал :)
  • Seed для CRC32?

    Lite_stream
    @Lite_stream Автор вопроса
    mayton2019, да не, в том исходнике я исключительно тестировал за сколько он подберёт нужную хеш функцию )
  • Seed для CRC32?

    Lite_stream
    @Lite_stream Автор вопроса
    mayton2019, ну я пытался сделать эмуляцию заполнения внутренней хеш таблицы, в данном случае с load_factor = 16/14. Смотрел за сколько попыток в среднем это произойдёт (найдётся h2i что не будет коллизий)
  • Seed для CRC32?

    Lite_stream
    @Lite_stream Автор вопроса
    mayton2019, она, например, в ClickHouse'е используется для интов + как внутрення часть для cityHash для строк
    ну и я сам посмотрел на некоторых дата-сетах у неё хорошее распределение
  • Seed для CRC32?

    Lite_stream
    @Lite_stream Автор вопроса
    mayton2019, о, вот это её минус главный, внешняя таблица ~2n, а размер внутренней ~5, если до ближайшей степени 2, то 8, и того 2n * 8 = 16n
  • Seed для CRC32?

    Lite_stream
    @Lite_stream Автор вопроса
    mayton2019, ты сначала функцией h1 хешируешь во внешнюю хеш таблицу итемы, а потом для каждой ячейки внешней хеш таблицы подбираешь такую h2i, что все итемы ячейки захешируются без коллизий
  • Seed для CRC32?

    Lite_stream
    @Lite_stream Автор вопроса
  • Seed для CRC32?

    Lite_stream
    @Lite_stream Автор вопроса
    mayton2019, немного не понял как тут поможет кукушка, можно подробнее плз )

    Ну и я про кукушку говорил в контексте того, чтобы contains всегда за O(1), не амортизированно
  • Seed для CRC32?

    Lite_stream
    @Lite_stream Автор вопроса
    mayton2019, короче выяснил, что для некоторого набора данных (ключей) существуют такие параметры (на картинке - evil_param), что если нарисовать граф, где вершина - это параметр, а ребро - текущий ключ + текущий параметр, то появляется цикл в таком графе

    Поборосял с этим дефолтным способом: если алгоритм сильно много итераций не сходится, то меняю параметр на рандомный и пытаясь заново, вроде работает

    Как я понял, с инкрементальными seed'ами просто вероятность в такой цикл попасть больше

    Граф
  • Seed для CRC32?

    Lite_stream
    @Lite_stream Автор вопроса
    mayton2019, вот гпт 3.5 дал мне ответ, хотя и довольно поверхностный, хотелось бы мат. обоснование


    Да, для данной конкретной ситуации с хеш-функцией CRC32 можно предложить математическое объяснение такого поведения.

    CRC32 - это циклический редундантный код (Cyclic Redundancy Check), который обычно используется для обнаружения ошибок в данных. Он оперирует с битами данных и вычисляет контрольную сумму для обнаружения ошибок в передаче данных.

    При использовании CRC32 в вашем коде в качестве параметра хеш-функции для хэш-таблицы, вы фактически создаете некоторую последовательность хешей, каждый из которых зависит от предыдущего. Так как CRC32 обрабатывает данные по битам и вычисляет контрольную сумму, его свойства обеспечивают некоторую случайность и разнообразие в вычисленных хеш-значениях.

    Когда вы используете хеш с предыдущей итерации для получения нового хеша (25-я строка), вы создаете последовательность хешей, которая зависит от предыдущих значений. Это приводит к тому, что каждый следующий хеш зависит от предыдущего и от входных данных (ключей), и, таким образом, обеспечивает разнообразие хешей. Кроме того, при каждом исполнении цикла происходит пересчет хеш-значения с новым параметром, что увеличивает разнообразие хешей в процессе.

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

    Таким образом, математическое объяснение заключается в том, что использование CRC32 и его свойства циклического редундантного кода, а также зависимость от предыдущего значения, обеспечивают разнообразие хешей при использовании хеша с предыдущей итерации. Это позволяет алгоритму быстро находить подходящий параметр для успешного заполнения бакета без коллизий.
  • Seed для CRC32?

    Lite_stream
    @Lite_stream Автор вопроса
    mayton2019, ну если всё равновероятно, то 0.25 * 1 + 0.25 * 2 + 0.5 * 2 = 1.75 (0.25 * 1 - элемент есть и он в 1-й ячейке, 0.25 * 2 - элемент есть и он во 2-й ячейке, 0.5 * 2 - элемента нет)
    Предполагается, что contains на одни и те же элементы не вызывается, а если вызывается, то их уже нет в кеше )
  • Идеальное хеширование без чтения из памяти параметров h2(k)?

    Lite_stream
    @Lite_stream Автор вопроса
    mayton2019, ну у фильтра блума вообще будет K кэш миссов в среднем )
    Тут-то я вообще с 2-х до 1-го хочу улучшить
  • Идеальное хеширование без чтения из памяти параметров h2(k)?

    Lite_stream
    @Lite_stream Автор вопроса
    mayton2019, да нет, если какой-то код, в данном случае contains(k), читал дважды из памяти (при этом времени на вычисления тратил совсем немного), то уменьшение количества обращений к памяти в 2 раза увеличит скорость работы этого кода тоже почти вдвое. А contains(k) у PerfectHashTable фактически единственный метод
  • Идеальное хеширование без чтения из памяти параметров h2(k)?

    Lite_stream
    @Lite_stream Автор вопроса
    mayton2019, ну и необязательно справочники, которые содержат данные вроде стран.
    Такая хеш таблица может быть вспомогательной структорой данных в каком-то другом алгоритме, тогда время её1 построения критично.
    Или, например, список каких-то (их не так много, что можно хранить в оперативке, а не на диске) user'ов в оперативной памяти сервера, на старте сервера можно сбилдить таблицу, и запомнить max id (key) user'a, и при запросе contains, если id <= max id, то идти в эту статическую хеш таблицу, иначе в динамическую
  • Идеальное хеширование без чтения из памяти параметров h2(k)?

    Lite_stream
    @Lite_stream Автор вопроса
    mayton2019, так вариант с двумя как раз и противопоставляют варианту с одной, там как раз смысл в том, что квадрат растёт нелинейно и ((m/n)^2)*n (где (m/n)^2 размер бакета) много лучше n^2 (там примерно ((m/n)^2)*n ~ 4n получается при допустимом по времени построения размеру бакета)
  • Идеальное хеширование без чтения из памяти параметров h2(k)?

    Lite_stream
    @Lite_stream Автор вопроса
    mayton2019, забыл упомянуть в самом вопросе, что вариант с размером хеш таблицы m = n^2, где в среднем за 2 раза удастся построить таблицу (только с одной внейшней h1, без h2i) не подходит из-за больших затрат по памяти.

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