Разница в производительности между map и неупорядоченной картой в c++

У меня есть простое требование, мне нужна карта типа . однако мне нужно самое быстрое теоретически возможное время поиска.

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

карта заняла всего 2 минуты, в то время как unordered_map занял 5 минут.

Как я, он будет частью кода, который будет выполняться на кластере Hadoop и будет содержать ~100 миллионов записи, мне нужно как можно меньше времени на поиск.

также еще одна полезная информация: в настоящее время вставляемые данные (ключи) представляют собой диапазон целых чисел от 1,2,... в ~10 миллионов.

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

вот код

map<int,int> Label // this is being changed to unordered_map  
fstream LabelFile("Labels.txt");  


// Creating the map from the Label.txt  
if (LabelFile.is_open())  
{  
    while (! LabelFile.eof() )  
    {             
        getline (LabelFile,inputLine);  
        try  
        {  
            curnode=inputLine.substr(0,inputLine.find_first_of("t"));  
            nodelabel=inputLine.substr(inputLine.find_first_of("t")+1,inputLine.size()-1);  
            Label[atoi(curnode.c_str())]=atoi(nodelabel.c_str());  
        }  
        catch(char* strerr)  
        {  
            failed=true;  
            break;  
        }  
    }  
    LabelFile.close(); 
}

предварительное решение: после просмотра комментариев и ответов я считаю, что динамический массив C++ будет лучшим вариантом, так как реализация будет использовать плотные ключи. Спасибо

3 ответов


вставка для unordered_map должна быть O (1) и поиск должен быть примерно O (1), (его, по сути, хэш-таблицы).

ваши тайминги в результате пути выкл, или есть что-то неправильно С вашей реализацией или использованием unordered_map.

вам нужно предоставить дополнительную информацию и, возможно, как вы используете контейнер.

согласно разделу 6.3 из n1836 сложности для вставки/поисковая указаны:

одна проблема, которую вы должны учитывать, заключается в том, что ваша реализация может постоянно быть rehashing структура, как вы говорите, у вас есть 100mil + элементы. В этом случае при создании экземпляра контейнера, если у вас есть приблизительное представление о том, сколько "уникальный" элементы будут вставлены в контейнер, вы можете передать это в качестве параметра конструктору, и контейнер будет создан соответствующим образом с помощью таблицы ведра соответствующего размера.


дополнительное время загрузки unordered_map связано с динамическим изменением размера массива. Расписание изменения размера должно удвоить количество ячеек, когда таблица превышает коэффициент загрузки. Поэтому из пустой таблицы ожидайте o (lg n) копий всей Таблицы данных. Вы можете устранить эти дополнительные копии, предварительно определив размер хэш-таблицы. В частности,

Label.reserve(expected_number_of_entries / Label.max_load_factor());

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


unordered_map (по крайней мере, в большинстве реализаций) дает быстрый поиск, но относительно низкую скорость вставки по сравнению с map. Дерево обычно в лучшем случае, когда данные упорядочены случайным образом, и в худшем случае, когда данные упорядочены (вы постоянно вставляете на одном конце дерева, увеличивая частоту повторной балансировки).

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

Edit: да, вектор в основном является динамическим массивом.

Edit2: код, который вы добавили некоторые проблемы. Ваш while (! LabelFile.eof() ) разбито. Обычно вы хотите сделать что-то вроде while (LabelFile >> inputdata) вместо. Вы также читаете данные несколько неэффективно - то, что вы, по-видимому, ожидаете, - это два числа, разделенные вкладкой. В таком случае, я бы написал цикл что-то например:

while (LabelFile >> node >> label)
    Label[node] = label;