Для начала многие стандартные хеш-реализации стандартной библиотеки с функцией идентификации, то есть hash(x) == x
. Обычно это нормально, особенно если реализация гарантирует, что подсчет ведра является простым (например, GCC), но в некоторых реализациях используются значения мощности из двух ведро (например, Visual C++). Вы можете запустить некоторые цифры через вашу хеш-функцию и посмотреть, является ли она функцией идентификации: если да, подумайте, достаточно ли ваши входы случайным образом, чтобы это не имело значения. Например, если ваши номера все кратные 4, то подсчет количества секунд из двух единиц означает, что вы используете только четверть ваших ковшей. Если они имеют тенденцию отличаться большей частью в старших битах, это также является проблемой, потому что побитовое-И с количеством из двух ведро ковша эффективно выбрасывает некоторое количество бит старшего порядка (например, с 1024 ведрами только 10 наименее значимых бит хэш-значения повлияет на выбор ковша).
Хороший способ проверить, для этого типа проблемы перебрать ваших ведер и создать гистограмму числа сталкивающихся элементов, например - с учетом unordered_map
m
:
std::map<int, int> histogram;
for (size_t i = 0; i < m.bucket_count(); ++i)
++histogram[m.bucket_size(i)];
for (auto& kv : histogram)
std::cout << ".bucket_size() " << kv.first << " seen "
<< kv.second << " times\n";
(Вы можете увидеть такие код запуска here).
Вы ожидаете, что частота больших значений bucket_size()
быстро проскользнет: если нет, работайте с хэш-функцией.
С другой стороны, если вы перешли сверху и создали свой unordered_map
с помощью хэш-шифрования на 512 бит или что-то еще, это лишний раз замедлит ваши операции с таблицами.Самый сильный хэш, который вам нужно учитывать при ежедневном использовании, с таблицами, имеющими менее 4 миллиардов элементов, - это 32-х мерный хеш. Тем не менее, используйте стандартную библиотеку при условии, если столкновение, о котором сообщалось выше, проблематично.
Переключение к закрытому адресации/открытой хеширования реализации хэш-таблицы (вы могли бы Google для одного), весьма вероятно, будет значительно быстрее, если у вас нет много «маслобойки»: удаление хеш-таблицы элементов почти в так же, как вы вставляете новые, с чередованием запросов. Закрытая адресация означает, что ключи хеш-таблицы хранятся непосредственно в ведрах, и вы получаете гораздо лучшие хиты кеша и намного быстрее перезаписываете по мере увеличения размера таблицы. Если значения, которыми располагаются ваши целые ключи, являются большими (с учетом размера памяти, как и в sizeof(My_Map::value_type)
), то убедитесь, что в нем хранятся только указатели на реализацию в самой таблице, поэтому во время изменения размера не нужно копировать все объекты.
Примечание: вышеупомянутое предполагает, что хеш-таблица действительно вызывает проблемы с производительностью. Если есть какие-либо сомнения, используйте профилировщик, чтобы подтвердить это, если вы еще этого не сделали.
Сколько мы говорим? –
Вы должны, по крайней мере, иметь возможность оценить порядок величины количества записей (1000, миллионы и т. Д.). –
Это зависит от имеющихся данных. Самое высокое, что я видел до сих пор, составляет около 2,9 миллиона записей –