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

    Lite_stream
    @Lite_stream Автор вопроса
    mayton2019, и да, нужно, чтобы запросов, где на contains/get было false/null, было мало, иначе в этом подходе не будет смысла особого
  • Seed для CRC32?

    Lite_stream
    @Lite_stream Автор вопроса
    mayton2019, кстати, насчёт "skewed histograms" на самом деле, хорошую идею подкинул, если такой шаблон встретился где-то.
    Действительно, можно отсортировать данные по частоте заросов на них, скажем на 10% объектов приходится 90% запросов contains/get, тогда можно с обычным линейным пробированием эти 10% запихать первыми (так, чтобы distance от места вставки до реального места был не больше 1.05 скажем), а остальные 90% запихать потом. Тогда мат. ожидание кеш мисса будет близко к 1.

    Единственный минус это большие таблицы. То есть, например, может так получиться, чтобы сохранить инвариант distance <= 1.05 для 10% объектов может потребоваться массив размером, например, 60n, если данных очень много. Из-за того что вероятность коллизии как квадрат растёт от n, к сожалению
  • Seed для CRC32?

    Lite_stream
    @Lite_stream Автор вопроса
    mayton2019, ну если речь идёт о статичной таблице (однажды построилась и далее с неё только читают, не модифицируют), то кукушка будет пробовать строиться, пока не построится так, чтобы каждому элементу было отведено место (не было циклов), ну а дальше просто запросы get/contains в зависимости от того мапа это или сет, ничего никуда больше перемещаться не будет))
  • Seed для CRC32?

    Lite_stream
    @Lite_stream Автор вопроса
    mayton2019, ну я хотел либо попробовать похешировать столько раз, чтобы distance от места вставки до реального расположения был небольше какой-то константы (как в робин гуде) ну и дальше что-то поулучшать там. Либо придумать так, чтобы кукушка из 2-х рандомных меств памяти не читала, либо читала но редко
  • 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-го хочу улучшить