Подтвердить что ты не робот

Почему карта будет намного быстрее, чем unordered_map?

Я реализовал результаты кэширования поиска, которые состоят из ключей типа State (класс с 7 короткими ints) и значений типа Socre (класс из 3 удваивается). Использование unordered_map было как минимум в 20 раз медленнее, чем карта. Почему?

Редактировать: Darn it! Моя хэш-функция была

namespace std {
    size_t hash<State>::operator()(State const& s) const {
        size_t retval = hash<short>()(s.s[0]);
        for (int i = 1; i < R; i += 2) {  // 1 3 5
            int x = (static_cast<int>(s.s[i + 1]) << 16)
                + (static_cast<int>(s.s[i]));
            hash_combine(retval, x);
        }
    }
}

Я забыл return retval, так что все это столкнулось! Я хочу, чтобы unordered_map имел функцию hash_function_quality(), которая сообщает о среднем числе столкновений.

4b9b3361

Ответ 1

Скорость unordered_map прямо пропорциональна скорости вашей хеширующей функции. Это никогда не прямые отношения. Например, если вы используете простейшую функцию хеширования:

std::size_t myHash(MyObjectType _object){ return 1; }

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

Что вам нужно сделать, это посмотреть на две вещи:

  • Какую функцию хеширования вы используете? Стоит ли смешное количество времени для обработки?
  • Сколько коллизий производится? То есть, сколько уникальных элементов сопоставляется с одним и тем же значением хеша?

Либо каждый из них может и может убить производительность.

Ответ 2

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

Ответ 3

std::unordered_map обычно медленный для небольшого числа элементов из-за хэш-функции. Требуется фиксированное (-иш) количество времени, но, возможно, значительное количество времени, тем не менее.

std::map, с другой стороны, проще, чем std::unordered_map. Время, необходимое для доступа к элементу, зависит от количества элементов, но все меньше и меньше, так как число элементов растет. А большой коэффициент c для std:: map тоже очень мал, по сравнению с std::unordered_map.

В общем, предпочитайте использовать std::map над std::unordered_map, если у вас нет конкретной причины использовать std::unordered_map. Это особенно важно, если у вас нет большого количества элементов.

Ответ 4

Для

Я хочу, чтобы unordered_map имел hash_function_quality(), которая сообщает среднее число столкновения.

Я думаю, что следующая функция может быть полезна.

unordered_map::load_factor
    float load_factor() const;
The member function returns the average number of elements per bucket.

Опустите load_factor, лучше хеш-функция.