C std ::unordered_map медленнее, чем std::map?

#c #stl

#c #stl

Вопрос:

В приведенном ниже примере я ожидал unordered_map , что будет быстрее map , но это не так. Почему это так? unordered_map Предназначен для другой цели, а не для того, чтобы быть быстрее обычной карты?

 #include <iostream>
#include <chrono>
#include <unordered_map>
#include <map>


int main()
{
    std::unordered_map<int, double> grid_unmap_int;
    std::map<int, double> grid_map_int;
    
    size_t map_size = 1e7;

    auto t1 = clock();
    for (size_t i = 0; i < map_size;   i) {
        grid_unmap_int[i] = 1.0;
    }
    auto t2 = clock();


    for (size_t k = 0; k < map_size;   k) {
        grid_map_int[k] = 1.0;
    }
    auto t3 = clock();

    std::cout << "Insertion n";
    std::cout << "Filling unordered map int key: " << (t2 - t1) / static_cast<double>(CLOCKS_PER_SEC) << " seconds.n";
    std::cout << "Filling map int key: " << (t3 - t2) / static_cast<double>(CLOCKS_PER_SEC) << " seconds.n";
    std::cout << std::endl;

    t1 = clock();
    for (size_t i = 0; i < map_size;   i) {
        double b = grid_unmap_int[i] ;
    }
    t2 = clock();


    for (size_t k = 0; k < map_size;   k) {
        double b = grid_map_int[k];
    }
    t3 = clock();

    std::cout << "Retrieve n";
    std::cout << "Filling unordered map int key: " << (t2 - t1) / static_cast<double>(CLOCKS_PER_SEC) << " seconds.n";
    std::cout << "Filling map int key: " << (t3 - t2) / static_cast<double>(CLOCKS_PER_SEC) << " seconds.n";


    return 0;
}
 

Редактировать:
результаты:
введите описание изображения здесь

Комментарии:

1. unordered_map он не предназначен для того, чтобы работать быстрее , чем обычная карта. Они работают по-разному. Точно так же, как вектор или список. Вы не можете назвать один из них самым быстрым или лучшим . У них есть сильные и слабые стороны, и какая из них использовать, зависит от вашего варианта использования.

2. Вы заявляете о производительности без предоставления статистики или флагов компиляции.

3. быстрый тест предполагает, что на самом деле unordered_map в 5 раз быстрее для вашего конкретного тестового примера: quick-bench.com/q/OK0XfUYBuko17quF1edWLIgLdK8

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

5. Вы использовали -O3 ? В моей системе unordered_map в 2,8 раза быстрее для вставки и в 10 раз быстрее для извлечения.

Ответ №1:

В приведенном ниже примере я ожидал unordered_map , что будет быстрее map , но это не так. Почему это так?

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

Это причудливый способ сказать: «Могло быть лучше, а могло быть и хуже. Профилируйте его для вашего конкретного сценария «.

unordered_map Предназначен ли он для другой цели, чем быть быстрее обычного map ?

ДА.

std::map можно использовать только те ключи, которые заказаны. Должен быть устоявшийся способ сортировки типа, как int в вашем примере. И в свою очередь, повторение std::map дает вам такой порядок.

std::unordered_map можно использовать только ключи, для которых std::hash<Key> определено. Ключи не обязательно должны иметь установленный порядок (например, это могут быть изображения. Или цвета. Или звуки.) Но должен существовать какой-то способ преобразования значений в хэши.

Комментарии:

1. На самом деле сложность нам вообще мало что говорит. O(exp (n)) может быть быстрее, чем O (1) для всех достижимых n (например, n <= максимальный размер памяти), если с последним связана какая-то огромная константа. И это не какой-то абстрактный аргумент. Именно по этой причине, например, широко используется быстрая сортировка, хотя существуют алгоритмы с большей сложностью (например, сортировка слиянием).

2. @freakish ты абсолютно прав. Сложность пытается описать масштабируемость , а не скорость . Который сам по себе взрывается, если при увеличении масштаба происходит изменение O (1) на O (n).

3. Я хочу сказать, что все еще существуют некоторые ожидания относительно производительности, независимо от сложности. Особенно в этом случае. Я знаю, что нет никаких гарантий, но почти все будут использовать map вместо unordered_map без измерения, когда упорядочивание не требуется. Также о порядке: на самом деле все объекты могут быть упорядочены. В конце концов, каждый объект представлен в виде некоторого числа. Потенциально огромный, как, например, изображение, но все же число.

4. @freakish вы можете отредактировать этот ответ, если какая-либо формулировка вам не кажется правильной. Возможно, я недостаточно четко объяснил, что «упорядочение» отличается от того, возможно ли упорядочить.