Сверхвысокопроизводительная хеш-карта C / C ++ (таблица, словарь) [закрыто]


86

Мне нужно сопоставить примитивные ключи (int, возможно, long) для структурирования значений в высокопроизводительной структуре данных хэш-карты.

В моей программе будет несколько сотен таких карт, и каждая карта обычно содержит не более нескольких тысяч записей. Однако карты будут постоянно «обновляться» или «вспениваться»; представьте обработки миллионы addи deleteсообщений в секунду.

Какие библиотеки на C или C ++ имеют структуру данных, подходящую для этого варианта использования? Или как бы вы порекомендовали создать свой собственный? Благодаря!


1
Вам нужно обработать поиск по ключам в ваших данных?
Guillaume Lebourgeois

3
будут ли обновления или поиски более частыми? (добавить / удалить или прочитать / обновить, не меняя ключ)
falstro

stackoverflow.com/questions/266206/… . Возможно, это хорошее место для начала.
DumbCoder

2
@roe:Операции добавления / удаления выполняются намного (в 100 раз) чаще, чем операция получения.
Haywood Jablomey

1
Спустя четыре с половиной года было бы интересно узнать, что лучше всего соответствует вашим потребностям. Если ни один из текущих ответов не был удовлетворительным, вы можете написать свой и принять его.
Уолтер Тросс,

Ответы:


31

Я бы порекомендовал вам попробовать Google SparseHash (или версию C11 Google SparseHash-c11 ) и посмотреть, подходит ли он вашим потребностям. У них есть реализация с эффективным использованием памяти, а также оптимизированная по скорости. Давным-давно я провел тест, это была лучшая реализация хеш-таблицы, доступная с точки зрения скорости (однако с недостатками).


16
Не могли бы вы рассказать о недостатках?
Haywood Jablomey

IIRC, это была проблема с памятью, при удалении элемента элемент был разрушен, но его память все еще была жива (я думаю, использовалась как кеш).
Scharron

4
@Haywood Jablomey: Главный недостаток состоит в том, что вам нужно разделить одно или два (если вы когда-нибудь стираете элементы) значения и никогда их не использовать. В некоторых случаях это легко сделать, например, отрицательные целые числа или тому подобное, но в других случаях не совсем так.
doublep

3
Вы бы поддержали эту рекомендацию сегодня?
einpoklum

11

Какие библиотеки на C или C ++ имеют структуру данных, подходящую для этого варианта использования? Или как бы вы порекомендовали создать свой собственный? Благодаря!

Обратите внимание на массивы Джуди от LGPL . Сам никогда не использовал, но несколько раз мне рекламировали.

Вы также можете попробовать протестировать контейнеры STL (std :: hash_map и т. Д.). В зависимости от платформы / реализации и настройки исходного кода (предварительное выделение максимально возможного объема динамической памяти стоит дорого) они могут быть достаточно производительными.

Кроме того, если производительность окончательного решения превышает стоимость решения, вы можете попробовать заказать систему с достаточным объемом оперативной памяти, чтобы поместить все в простые массивы. Производительность доступа по индексу не имеет себе равных.

Операции добавления / удаления выполняются намного (в 100 раз) чаще, чем операция получения.

Это намекает на то, что вы можете в первую очередь сосредоточиться на улучшении алгоритмов. Если данные только записываются, а не читаются, тогда зачем их вообще писать?


11

Просто используйте boost::unordered_map(или tr1т. Д.) По умолчанию. Затем профилируйте свой код и посмотрите, является ли этот код узким местом. Только после этого я предлагаю тщательно проанализировать ваши требования, чтобы найти более быструю замену.


15
Это. VS2013 std::unordered_mapзанимает 90 +% всего моего времени выполнения, хотя я использую карты только для относительно небольшой части обработки.
Кэмерон

6

Если у вас есть многопоточная программа, вы можете найти несколько полезных хеш-таблиц в библиотеке строительных блоков Intel thread . Например, tbb :: concurrent_unordered_map имеет тот же API, что и std :: unordered_map, но его основные функции являются потокобезопасными.

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




2

Сначала проверьте, подходят ли существующие решения, такие как libmemcache, вашим потребностям.

Если не ...

Хеш-карты кажутся однозначным ответом на ваши требования. Он обеспечивает поиск o (1) на основе ключей. В наши дни большинство библиотек STL предоставляют какой-то хэш. Так что используйте тот, который предоставляется вашей платформой.

Как только эта часть будет завершена, вы должны протестировать решение, чтобы убедиться, что алгоритм хеширования по умолчанию достаточно хорош для ваших нужд.

Если это не так, вам следует изучить несколько хороших алгоритмов быстрого хеширования, которые можно найти в сети.

  1. старый добрый алгоритм умножения простых чисел
  2. http://www.azillionmonkeys.com/qed/hash.html
  3. http://burtleburtle.net/bob/
  4. http://code.google.com/p/google-sparsehash/

Если этого недостаточно, вы можете самостоятельно скатить модуль хеширования, который устранит проблему, которую вы видели с тестированными контейнерами STL, и одним из алгоритмов хеширования, описанных выше. Обязательно где-нибудь выложите результаты.

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

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

Я считаю, что больше, чем алгоритм хеширования, это может быть постоянное добавление / удаление памяти (можно ли этого избежать?) И профиль использования кеша процессора, который может быть более важным для производительности вашего приложения.

удачи


2

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


2

Я бы предложил утхаш . Просто включите, #include "uthash.h"затем добавьте UT_hash_handleв структуру и выберите одно или несколько полей в своей структуре, которые будут действовать в качестве ключа. Слово о производительности здесь .


1

http://incise.org/hash-table-benchmarks.html gcc имеет очень хорошую реализацию. Однако учтите, что он должен учитывать очень плохое стандартное решение:

Если происходит повторное хеширование, все итераторы становятся недействительными, но ссылки и указатели на отдельные элементы остаются действительными. Если фактического повторного хеширования не происходит, никаких изменений.

http://www.cplusplus.com/reference/unordered_map/unordered_map/rehash/

Это означает, что стандарт говорит, что реализация ДОЛЖНА БЫТЬ основана на связанных списках. Это предотвращает открытую адресацию, которая имеет лучшую производительность.

Я думаю, что Google Sparse использует открытую адресацию, хотя в этих тестах только плотная версия превосходит конкурентов. Однако разреженная версия превосходит всех конкурентов по использованию памяти. (также у него нет плато, чистая прямая линия по количеству элементов)


1
См. Также это , где обсуждается, как интерфейс корзины также требует цепочки. Дело в ссылках очень хорошее. Заманчиво поспорить и сказать, что это полезная гарантия, но во многих случаях нам нужны только ссылки, чтобы избежать повторного поиска элементов, и обычная причина заключается в том, что поиск выполняется слишком медленно ... чего бы не было, если бы он не должны поддерживать ссылки в силе и, следовательно, могут использовать открытую адресацию! Так что это немного похоже на курицу и яйцо. Здесь цитируется предложение 2003 года, в котором явно обсуждается выбор.
underscore_d
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.