Кукушка хеширование в C
У кого-нибудь есть реализация хеширование кукушки в C? Если бы был открытый исходный код, не версия GPL, это было бы идеально!
поскольку Адам упомянул об этом в своем комментарии, кто-нибудь знает, почему это не используется? Это просто вопрос реализации или хорошие теоретические свойства не материализуются на практике?
8 ответов
как указывали другие ответы, это правда, что самый простой хэш-таблица кукушки требует, чтобы таблица была наполовину пустой. Однако понятие было обобщено на d - Ары кукушка хеширование, в котором каждый ключ имеет d возможные места для гнезда, в отличие от 2 мест в простой версии.
приемлемый коэффициент нагрузки увеличивается быстро, как d увеличивается. Только для d=3, вы уже можете использовать около 75% полная таблица. Этот недостатком является то, что вам нужно d независимые хеш-функции. Я поклонник хэш-функций Боба Дженкинса для этой цели (см.http://burtleburtle.net/bob/c/lookup3.c), который вы можете найти полезным в реализации хэширования кукушки.
хеширование кукушки относительно не используется вне академических кругов (кроме аппаратных кэшей, которые иногда заимствуют идеи, но на самом деле не реализуют полностью). Это требует очень разреженной хэш-таблицы, чтобы получить хорошее время на вставках - вам действительно нужно иметь 51% вашей таблицы пустой для хорошей производительности. Таким образом, он либо быстрый и занимает много места, либо медленный и эффективно использует пространство - никогда не оба. Другие алгоритмы эффективны как во времени, так и в пространстве, хотя они хуже, чем cuckoo, когда учитывается только время или пространство.
здесь генератор кода для хеш-таблиц cuckoo. Проверьте лицензию генератора, чтобы убедиться, что выход не является GPL. Должно быть, но все равно проверь.
Адам
хотя это старый вопрос, кто-то еще может быть интересно :)
этой статье описывает реализацию параллельного хэша D-ary cuckoo на графических процессорах (CUDA / OpenCL). Он описан очень хорошо, и его реализация на основе описания довольно проста. Вообще стоит почитать, если вас интересует эта тема. (Вам понадобится ACM-логин.)
язык ввода-вывода имеет один, в PHash.c. Вы можете найти код для ввода-вывода на Github. IO имеет лицензию BSD.
Я вижу смысл в использовании, но это было мое обоснование для попытки этой конкретной схемы хэширования. Пожалуйста, дайте мне знать, если я что-то пропустил.
насколько мне известно, возможными альтернативами хэш-таблицам для создания динамического словаря являются (сбалансированные) двоичные деревья и скиплисты. Просто для обсуждения давайте абстрагируемся от типов ключей и значений и предположим, что мы получим доступ к значениям через void *
.
для двоичного дерева я бы есть:
struct node {
void *key;
void *value;
struct node *left;
struct node *right;
}
Итак, предполагая, что указатели имеют одинаковый размер s, в магазине n элементы, которые мне понадобятся 4 s байт.
Skiplists почти такие же, как среднее количество указателей в узле-2.
в хэш-таблице у меня было бы:
struct slot {
void *key;
void *value;
}
таким образом, каждый элемент будет только requre 2 s байты для хранения. Если коэффициент загрузки составляет 50%, хранить n детали мне будут нужны же 4 s байт, как деревья.
мне это не кажется слишком плохим: хэш-таблица cuckoo будет занимать более или менее тот же объем памяти, что и двоичное дерево, но даст мне O(1) время доступа, а не O(log n).
не считая сложности поддержания сбалансированности дерева и дополнительной информации, которая может потребоваться для хранения балансирующей информации в узле.
другие схемы хэширования могут достичь лучшего коэффициента нагрузки (скажем, 75% или 80%) с нет гарантии на худший случай времени доступа(это может быть даже O (n) ).
кстати, д-ичных кукушка хеширования и "кукушка хеширование с заначкой" кажется, можно увеличить коэффициент загрузки, сохраняя при этом постоянное время доступа.
Я не могу говорить о программном обеспечении, но хеширование кукушки, безусловно, используется в аппаратном обеспечении и становится очень популярным. Основные поставщики сетевого оборудования изучают хеширование кукушки, а некоторые уже используют его. Притяжение к хешированию кукушки происходит от постоянного времени поиска, конечно, но также и от почти постоянного времени вставки.
хотя теоретически вставка может быть неограниченной, на практике она может быть ограничена O (log n) числа строк в таблице(таблицах) и когда измеренное время вставки составляет в среднем около 1,1*d доступа к памяти. Это всего на 10% больше абсолютного минимума! Доступ к памяти часто является ограничивающим фактором в сетевом оборудовании.
независимые хэш-функции являются обязательными, и их правильный выбор затруднен. Удача.
после комментария от "onebyone" я реализовал и протестировал несколько версий хеширования Cuckoo, чтобы определить реальное требование к памяти.
после некоторого эксперимента утверждение, что вам не нужно переназначать, пока таблица не будет заполнена почти на 50%, кажется верным, особенно если "притон" трюк реализуемых.
проблема в том, когда вы увеличиваете таблицу. Обычный подход-удвоить его размер, но это приводит к тому, что новая таблица будет только 25% используется!
на самом деле, предположим, что хэш-таблица имеет 16 слотов, когда я вставляю номер 8-го элемента, у меня закончатся хорошие слоты и придется переназначить. Я удвою его, и теперь таблица 32 слота с только 8 из них заняты, что является 75% отходов!
это цена, которую нужно заплатить, чтобы иметь "постоянное" время извлечения (с точки зрения верхней границы для числа доступа/сравнения).
Я разработал другую схему, хотя: начиная с мощности 2 больше 1, если таблица имеет N слотов и N-степень двух, добавьте N/2 слотов в противном случае добавьте n / 3 слотов:
+--+--+
| | | 2 slots
+--+--+
+--+--+--+
| | | | 3 slots
+--+--+--+
+--+--+--+--+
| | | | | 4 slots
+--+--+--+--+
+--+--+--+--+--+--+
| | | | | | | 6 slots
+--+--+--+--+--+--+
+--+--+--+--+--+--+--+--+
| | | | | | | | | 8 slots
+--+--+--+--+--+--+--+--+
etc.
вместе с предположением, что переназначение будет происходить только тогда, когда таблица заполнена на 50%, это приводит к тому, что таблица будет только 66% пустой (1/3), а не 75% пустой (1/4) после reash (т. е. в худшем случае).
Я также выяснил (но мне все еще нужно проверить математику), что увеличение каждый раз на sqrt (n), потерянное пространство асимптотически приближается к 50%.
конечно, цена, которую нужно заплатить за меньшее потребление памяти, - это увеличение количества reash, которое будет необходимо в конце. Увы, ничего не дается бесплатно.
Я собираюсь исследовать дальше, если кто-то заинтересован.