Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> unordered_map<int,int> vs std::map<int,int>, что быстрее 
:(
    Опции темы
borisbn
Дата 10.11.2011, 15:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Привет всем.
Решил сравнить по скорости std::map и boost::unordered_map.
Почему-то думал, что для такого map< int, int > stl должен быть быстрее, т.к. он ведёт поиск в отсортированном дереве (или сбалансированном), а boost::unordered_map - в обычном, и хэш по int должен быть сам int, но оказалось всё с точностью до наоборот (unordered_map прилично быстрее). Объясните, пожалуйста, почему. 

вот код:
Код

std::map< int, int > std_m;
boost::unordered_map< int, int > boost_m;
std::vector< int > values;

const int N = 1000000;
int main()
{
    int t1, t2;
    for ( int i = 0; i < N; i++ )
        values.push_back( rand() * rand() );
    std::cout << "insert:" << std::endl;
    for ( int k = 0; k < 5; k++ ) {
        t1 = clock();
        for ( int i = 0; i < N; i++ )
            std_m[ values[ i ] ] = i;
        t2 = clock();
        std::cout << "std   : " << std::setw( 8 ) << (t2 - t1) / (double)CLOCKS_PER_SEC * 1000 << " ms." << std::endl;

        t1 = clock();
        for ( int i = 0; i < N; i++ )
            boost_m[ values[ i ] ] = i;
        t2 = clock();
        std::cout << "boost : " << std::setw( 8 ) << (t2 - t1) / (double)CLOCKS_PER_SEC * 1000 << " ms." << std::endl;
    }

    std::vector< int > temp( N );

    std::cout << std::endl << "size = " << std_m.size() << std::endl << std::endl;

    std::cout << "find[] :" << std::endl;
    for ( int k = 0; k < 5; k++ ) {
        t1 = clock();
        for ( int i = 0; i < N; i++ )
            temp[ i ] = std_m[ values[ i ] ];
        t2 = clock();
        std::cout << "std   : " << std::setw( 8 ) << (t2 - t1) / (double)CLOCKS_PER_SEC * 1000 << " ms. control : " << temp[ 42 ] << std::endl;

        t1 = clock();
        for ( int i = 0; i < N; i++ )
            temp[ i ] = boost_m[ values[ i ] ];
        t2 = clock();
        std::cout << "boost : " << std::setw( 8 ) << (t2 - t1) / (double)CLOCKS_PER_SEC * 1000 << " ms. control : " << temp[ 42 ] << std::endl;
    }
    std::cout << std::endl;
    std::cout << "find.find :" << std::endl;
    for ( int k = 0; k < 5; k++ ) {
        t1 = clock();
        for ( int i = 0; i < N; i++ )
            temp[ i ] = std_m.find( values[ i ] )->second;
        t2 = clock();
        std::cout << "std   : " << std::setw( 8 ) << (t2 - t1) / (double)CLOCKS_PER_SEC * 1000 << " ms. control : " << temp[ 42 ] << std::endl;

        t1 = clock();
        for ( int i = 0; i < N; i++ )
            temp[ i ] = boost_m.find( values[ i ] )->second;
        t2 = clock();
        std::cout << "boost : " << std::setw( 8 ) << (t2 - t1) / (double)CLOCKS_PER_SEC * 1000 << " ms. control : " << temp[ 42 ] << std::endl;
    }
}

http://liveworkspace.org/code/b5b3d5f77cb5...09535c8e83dc5d8

Вот вывод:
Цитата

insert:
std   :      922 ms.
boost :      500 ms.
std   :      782 ms.
boost :      109 ms.
std   :      781 ms.
boost :      110 ms.
std   :      765 ms.
boost :      110 ms.
std   :      765 ms.
boost :      110 ms.

size = 994626

find[] :
std   :      750 ms. control : 42
boost :       94 ms. control : 42
std   :      750 ms. control : 42
boost :       94 ms. control : 42
std   :      750 ms. control : 42
boost :       93 ms. control : 42
std   :      750 ms. control : 42
boost :       94 ms. control : 42
std   :      766 ms. control : 42
boost :       78 ms. control : 42

find.find :
std   :      750 ms. control : 42
boost :       62 ms. control : 42
std   :      750 ms. control : 42
boost :       47 ms. control : 42
std   :      750 ms. control : 42
boost :       47 ms. control : 42
std   :      750 ms. control : 42
boost :       63 ms. control : 42
std   :      750 ms. control : 42
boost :       47 ms. control : 42


stl - из состава minGW 4.4.0 (который в свою очередь из состава QtSDK)
boost - с офф.сайта. версия 1.47.0 

P.S. Может ещё кто подскажет, почему поиск функцией find быстрее поиска оператором []...

Спасибо.


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
boostcoder
Дата 10.11.2011, 16:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



borisbn, дополни свой тест еще std::unordered_map, плиз.
PM WWW   Вверх
borisbn
Дата 10.11.2011, 16:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



boostcoder,
Цитата(borisbn @  10.11.2011,  15:53 Найти цитируемый пост)
stl - из состава minGW 4.4.0


Всё никак руки не доходят скачать твой minGW (с поддержкой 0x11) и прикрутить его к QtCreator'у.
Кста, может кто-нибудь это делал ?
Тогда подскажите как.



--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Alca
Дата 10.11.2011, 16:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3993
Регистрация: 14.6.2006

Репутация: 7
Всего: 50



Цитата

Тогда подскажите как.

Tools -> Options -> Qt4
Tools -> Options -> Tool Chains

Это сообщение отредактировал(а) Alca - 10.11.2011, 17:00


--------------------
PM WWW ICQ Skype Jabber   Вверх
borisbn
Дата 10.11.2011, 17:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Alca, там указывается, где расположен qmake, а не minGW


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
boostcoder
Дата 10.11.2011, 18:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



borisbn, если я ничего не путаю, то в 4.4.0 уже есть std::unordered*

Добавлено через 4 минуты
Цитата(borisbn @  10.11.2011,  16:52 Найти цитируемый пост)
Кста, может кто-нибудь это делал ?

user posted image
PM WWW   Вверх
borisbn
Дата 10.11.2011, 20:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Итак.
1. Сделал std::unordered_map в minGW 4.4.0
Вот код
http://liveworkspace.org/code/bc7579812ea4...a364184425dcffd
Вот рез-ты (на моей машине)
Цитата

insert:
std   :      937 ms.
boost :      516 ms.
std_u :      484 ms.
std   :      735 ms.
boost :      125 ms.
std_u :      125 ms.
std   :      750 ms.
boost :      109 ms.
std_u :      125 ms.
std   :      750 ms.
boost :      109 ms.
std_u :      125 ms.
std   :      750 ms.
boost :      125 ms.
std_u :      125 ms.

size = 994626

find[] :
std   :      735 ms. control : 42
boost :       94 ms. control : 42
std_u :       78 ms. control : 42
std   :      750 ms. control : 42
boost :       93 ms. control : 42
std_u :       79 ms. control : 42
std   :      750 ms. control : 42
boost :       78 ms. control : 42
std_u :       78 ms. control : 42
std   :      750 ms. control : 42
boost :       94 ms. control : 42
std_u :       78 ms. control : 42
std   :      750 ms. control : 42
boost :       78 ms. control : 42
std_u :       78 ms. control : 42

find.find :
std   :      812 ms. control : 42
boost :       63 ms. control : 42
std_u :       47 ms. control : 42
std   :      735 ms. control : 42
boost :       62 ms. control : 42
std_u :       63 ms. control : 42
std   :      750 ms. control : 42
boost :       47 ms. control : 42
std_u :       62 ms. control : 42
std   :      750 ms. control : 42
boost :       63 ms. control : 42
std_u :       62 ms. control : 42
std   :      750 ms. control : 42
boost :       47 ms. control : 42
std_u :       63 ms. control : 42


2. Судя по всему что std::, что boost:: unordered_map ведут себя одинакого
3. Мне всё равно непонятно, почему unordered быстрее "ordered"
4. А что с вопросом про operator[] vs unordered_map::find() ?
5. 2 boostcoder: что отсюда (http://code.google.com/p/mingw-builds/downloads/list) из этого списка
user posted image
мне поставить, чтобы: 1) была стабильная версия 2) чтобы был только Си++ (мне не нужен ни objC, ни fortran). Спасибо.


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
boostcoder
Дата 10.11.2011, 20:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(borisbn @  10.11.2011,  20:20 Найти цитируемый пост)
boostcoder: что отсюда (http://code.google.com/p/mingw-builds/downloads/list) из этого списка мне поставить, чтобы: 1) была стабильная версия 2) чтобы был только Си++ (мне не нужен ни objC, ни fortran).

описание для кого писал? smile 
Цитата

Какую сборку выбрать? - Все просто!

Если Вам нужна стабильная сборка, ищите сборки в именах которых присутствует "release". Например: 4.6.1-release-20110828 означает, что это сборка GCC версии 4.6.1, стабильная, дата сборки 20110828. Если в имени сборки присутствует "FINAL", это означает, что это последняя сборка этой версии компилятора, и, как правило - лучшая. Если суффикс равен "dwarf2" - значит этот компилятор реализует исключения используя DWARF2 технологию. Иначе SJLJ.

без фортрана и обжектив-си сборок нет. чтоб не плодить процесс сборки и архивы.

так что рекомендую эту:
4.6.2-release-c,c++,objc,objc++,fortran-dwarf
zip - http://mingw-builds.googlecode.com/files/m...rtran-dwarf.zip
7z - http://mingw-builds.googlecode.com/files/m...ortran-dwarf.7z
PM WWW   Вверх
Леопольд
Дата 10.11.2011, 20:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 943
Регистрация: 17.6.2009

Репутация: 10
Всего: 13



Цитата(borisbn @  10.11.2011,  20:20 Найти цитируемый пост)
4. А что с вопросом про operator[] vs unordered_map::find() ?
Тестировался оптимизированный код?


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
borisbn
Дата 10.11.2011, 21:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



boostcoder, премного благодарен. Скачаю, установлю, настрою - отпишусь.
А если, всё-таки, "вернуться к нашим баранам"... Что по теме ?
Почему unordered быстрее ordered ?

Цитата(Леопольд @  10.11.2011,  20:41 Найти цитируемый пост)
Тестировался оптимизированный код?

Честно говоря, просто выбрал тип сборки Release...
Сейчас посмотрел сгенерённый qmake'ом Makefile.Release:
Цитата

...
CFLAGS        = -O2 -Wall $(DEFINES)
...

больше ничего относящегося к компилятору не нашёл. Нужно будет - могу весь Makefile выложить


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
boostcoder
Дата 10.11.2011, 21:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(borisbn @  10.11.2011,  21:22 Найти цитируемый пост)
Почему unordered быстрее ordered ?

тут неплохо описывается: http://lanzkron.wordpress.com/2010/06/02/o...tz-for-klutzes/

Добавлено через 14 минут и 27 секунд
borisbn, так ты допишешь в тест std::unordered_map?
PM WWW   Вверх
borisbn
Дата 10.11.2011, 22:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Цитата(boostcoder @  10.11.2011,  21:37 Найти цитируемый пост)
так ты допишешь в тест std::unordered_map?


Цитата(borisbn @  10.11.2011,  20:20 Найти цитируемый пост)
1. Сделал std::unordered_map в minGW 4.4.0
Вот код
http://liveworkspace.org/code/bc7579812ea4...a364184425dcffd
Вот рез-ты (на моей машине)


Цитата(borisbn @  10.11.2011,  21:22 Найти цитируемый пост)
Скачаю, установлю, настрою - отпишусь.

скачал, установил, настроил - работает  smile 
правда долго тупил, что дать креатору в качестве компилятора - c++.exe, g++.exe, gcc.exe, i686-pc-mingw32-c++.exe, i686-pc-mingw32-g++.exe, i686-pc-mingw32-gcc-4.6.2.exe или i686-pc-mingw32-gcc.exe...
в общем остановился на g++.

Цитата(boostcoder @  10.11.2011,  21:37 Найти цитируемый пост)
тут неплохо описывается:

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


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
boostcoder
Дата 10.11.2011, 22:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(borisbn @  10.11.2011,  22:15 Найти цитируемый пост)
в общем остановился на g++.

угу.

Цитата(borisbn @  10.11.2011,  22:15 Найти цитируемый пост)
Так что, получается в unordered_map используется не дерево, а тупо массив, а мой ключ переводится в обычный индекс...

я этого тоже не понял. мне кажется это не верный вывод. наверняка автор что-то напутал... но разобраться в исходниках std::unordered_map ой как не просто.

Цитата(borisbn @  10.11.2011,  22:15 Найти цитируемый пост)

Цитата(boostcoder @  10.11.2011,  21:37 )
так ты допишешь в тест std::unordered_map?


Цитата(borisbn @  10.11.2011,  20:20 )
Сделал std::unordered_map в minGW 4.4.0
Вот код http://liveworkspace.org/code/bc7579812ea4...a364184425dcffd
Вот рез-ты (на моей машине)

как-то я не заметил smile

Добавлено через 1 минуту и 18 секунд
Цитата(borisbn @  10.11.2011,  20:20 Найти цитируемый пост)
Сделал std::unordered_map в minGW 4.4.0

а с 4.6.2 результаты такие же? а то со времен 4.4.0 многое изменилось.

Добавлено через 2 минуты и 44 секунды
мои результаты:
Цитата

insert:
std   :      960 ms.
boost :      650 ms.
std_u :      450 ms.
std   :      850 ms.
boost :      250 ms.
std_u :      160 ms.
std   :      840 ms.
boost :      240 ms.
std_u :      160 ms.
std   :      860 ms.
boost :      250 ms.
std_u :      160 ms.
std   :      840 ms.
boost :      250 ms.
std_u :      160 ms.

size = 999811

find[] :
std   :      840 ms. control : 42
boost :      240 ms. control : 42
std_u :      160 ms. control : 42
std   :      840 ms. control : 42
boost :      240 ms. control : 42
std_u :      160 ms. control : 42
std   :      840 ms. control : 42
boost :      240 ms. control : 42
std_u :      160 ms. control : 42
std   :      830 ms. control : 42
boost :      250 ms. control : 42
std_u :      150 ms. control : 42
std   :      840 ms. control : 42
boost :      250 ms. control : 42
std_u :      150 ms. control : 42

find.find :
std   :      850 ms. control : 42
boost :      250 ms. control : 42
std_u :      160 ms. control : 42
std   :      830 ms. control : 42
boost :      240 ms. control : 42
std_u :      160 ms. control : 42
std   :      840 ms. control : 42
boost :      250 ms. control : 42
std_u :      160 ms. control : 42
std   :      870 ms. control : 42
boost :      260 ms. control : 42
std_u :      170 ms. control : 42
std   :      830 ms. control : 42
boost :      250 ms. control : 42
std_u :      160 ms. control : 42

стандартный умап однозначно рвет всех. это не может не радовать smile
PM WWW   Вверх
borisbn
Дата 10.11.2011, 22:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



вот на 4.6.2
Цитата

insert:
std   :      906 ms.
boost :      469 ms.
std_u :      469 ms.
std   :      750 ms.
boost :      125 ms.
std_u :      125 ms.
std   :      750 ms.
boost :      109 ms.
std_u :      125 ms.
std   :      750 ms.
boost :      125 ms.
std_u :      110 ms.
std   :      750 ms.
boost :      125 ms.
std_u :      125 ms.

size = 994626

find[] :
std   :      750 ms. control : 42
boost :       78 ms. control : 42
std_u :       62 ms. control : 42
std   :      750 ms. control : 42
boost :       78 ms. control : 42
std_u :       63 ms. control : 42
std   :      750 ms. control : 42
boost :       78 ms. control : 42
std_u :       63 ms. control : 42
std   :      750 ms. control : 42
boost :       78 ms. control : 42
std_u :       62 ms. control : 42
std   :      750 ms. control : 42
boost :       78 ms. control : 42
std_u :       63 ms. control : 42

find.find :
std   :      750 ms. control : 42
boost :       47 ms. control : 42
std_u :       78 ms. control : 42
std   :      734 ms. control : 42
boost :       63 ms. control : 42
std_u :       62 ms. control : 42
std   :      735 ms. control : 42
boost :       62 ms. control : 42
std_u :       63 ms. control : 42
std   :      750 ms. control : 42
boost :       46 ms. control : 42
std_u :       63 ms. control : 42
std   :      750 ms. control : 42
boost :       47 ms. control : 42
std_u :       78 ms. control : 42


относительно 4.4.0 поменялось только время получения элемента оператором [] - оно теперь равно find'овскому ( что также не может не радовать smile ). Так что вопрос по оператору [] снимается

А ещё не может не радовать, что теперь exe-шник не требует minGW-шных и libc-шных dll-ек

Цитата(boostcoder @  10.11.2011,  22:26 Найти цитируемый пост)
но разобраться в исходниках std::unordered_map ой как не просто

я попытался и бросил - unordered_map наследуется от Hashtable, который, в свою очередь наследуется от Rehash_base, Hash_code_base, Map_base и Equality_base... бррррррр.


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
boostcoder
Дата 10.11.2011, 23:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(borisbn @  10.11.2011,  22:47 Найти цитируемый пост)
А ещё не может не радовать, что теперь exe-шник не требует minGW-шных и libc-шных dll-ек

я в своих сборках использую CRT проекта wingw-w64, что в свою очередь делает библиотеки собранные стандартным MinGW, несовместимыми с моей сборкой. так, к примеру, моей сборкой не получится слинковать QtSDK. Qt нужно пересобирать.
но я такой путь выбрал не зря. во первых - mingw.org предоставляет CRT только для 32-ух битных компиляторов. во вторых - проект очень слабо развивается, и, как признаются сами авторы, не имеет смысла на продолжение. он не будет переписан для 64-ех битных компиляторов.

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

Добавлено через 2 минуты и 22 секунды
ах да. об этом я уже писал тут smile 
http://forum.vingrad.ru/index.php?showtopi...t&p=2403408

Добавлено через 11 минут и 46 секунд
Цитата(boostcoder @  10.11.2011,  23:05 Найти цитируемый пост)
так, к примеру, моей сборкой не получится слинковать QtSDK. Qt нужно пересобирать.

если же использовать sjlj сборку - то слинкуется. но будет падать по сегфолту.
PM WWW   Вверх
borisbn
Дата 11.11.2011, 01:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Пообщался на ИРКе на эту тему - стало яснее. Приведу выдержки

Цитата

borisbn: Hi, here is a little test - http://ideone.com/UndgI. Question: why *unordered_map* is so quicker, then 'ordered' one ?
kuponut: borisbn: unordered_map should be quicker than an ordered...it's offering less promises, namely whether the data is in sorted order
borisbn: kuponut: but I didn't use string or other big arrays as a key. I used int. I think, that hash value for int == int
kuponut: borisbn: <map> offers insert/lookup os O(log n), <unordered_map> as amortized O(1)
borisbn: kuponut: you want to say, that unordered_map converts my int into the array index and just returns arr[ n ] ?
kuponut: borisbn: well, I'd imagine that unordered_map still hashes your int to some other int value, which is used as an index into an array
kuponut: borisbn: and there shouldn't (hopefully) be many entries in that index of the array, no matter how many total elements are in the map
borisbn: kuponut: in my test I have a map with size ~1 000 000. and I picked up them all. How could they use an array lesser then 1 000 000 ?
kuponut: borisbn: each index in the array holds linked nodes...two keys might hash to the same index, so in that index will be two nodes with the two values
kuponut: borisbn: so a lookup has to check both nodes at that index



--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
boostcoder
Дата 11.11.2011, 01:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(borisbn @  11.11.2011,  01:18 Найти цитируемый пост)
ИРКе

это чё?
PM WWW   Вверх
borisbn
Дата 11.11.2011, 06:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



http://ru.wikipedia.org/wiki/IRC - онлайн чат (древний как понятно что мамонта, но всё ещё актуальный).
Существует несколько серверов, предоставляющих IRC-чат. Самый крупный - freenode.net.
На каждом сервере есть н-ное количество тематических каналов. На freenode - ~30000 каналов.
Я там зависаю на #c++ (~1500 участников), #qt (~1000) и #boost (~800).
Клиенты - Веб-клиент из браузера ( http://webchat.freenode.net/ ), Miranda, mIRC, QIP Infium + плагин для протокола IRC.
Я пользую последний. Не самый удобный, но так я получаю 3 в 1 (jabber, twitter, IRC).


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
boostcoder
Дата 11.11.2011, 06:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



borisbn, очень познавательно smile 
но дело в том, что я, около полугода назад, перестал пользоваться всеми мессенджерами. слишком много времени уходит на треп.
PM WWW   Вверх
volatile
Дата 11.11.2011, 15:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 37
Всего: 85



borisbn, интересный тест, спасибо.

Безусловно, буст работает шустро, особенно на коротких значениях ключа, типа инт.
Тест на студии вашего кода, полностью подтвердил ваши данные, (с поправкой того что мой комп, в ~1.5 раза медленее вашего smile).
Но относительные занчения были прмерно такие-же.
Студийный стл::мап, надежно проигрывал, против буст-анордеред.
Студийный stdext::hash_map оказался не на много лучше.

И меня заинтересовало, насколько буст будет хорош, на длинных значениях.
В качестве ключей использовал std::string с разной длиной. 4, 30 и 300.
При длине 4, результаты полностью совпали с вашими.

При длине ключа 30:
hash_map, уже догнал, и даже немного перегнал boost
Код

insert:
std   :      797 ms.
boost :      578 ms.
hash  :      563 ms.

std   :      484 ms.
boost :      172 ms.
hash  :      109 ms.

std   :      485 ms.
boost :      171 ms.
hash  :      110 ms.


find[] :
std   :      500 ms.
boost :      156 ms.
hash  :      109 ms.

std   :      500 ms.
boost :      157 ms.
hash  :      125 ms.

std   :      484 ms.
boost :      156 ms.
hash  :      125 ms.


find.find :
std   :      485 ms.
boost :      156 ms.
hash  :      109 ms.

std   :      485 ms.
boost :      156 ms.
hash  :      125 ms.

std   :      484 ms.
boost :      157 ms.
hash  :      109 ms.


При длине ключа 300:
boost отстает не только от hash_map, но даже и от std::map
Код

insert:
std   :     1094 ms.
boost :     2859 ms.
hash  :     1250 ms.

std   :      672 ms.
boost :     1063 ms.
hash  :      375 ms.

std   :      672 ms.
boost :     1062 ms.
hash  :      375 ms.


find[] :
std   :      672 ms.
boost :     1063 ms.
hash  :      390 ms.

std   :      656 ms.
boost :     1079 ms.
hash  :      375 ms.

std   :      671 ms.
boost :     1063 ms.
hash  :      391 ms.


find.find :
std   :      656 ms.
boost :     1078 ms.
hash  :      375 ms.

std   :      656 ms.
boost :     1078 ms.
hash  :      375 ms.

std   :      657 ms.
boost :     1078 ms.
hash  :      375 ms.



Код, на котором я тестировал. (На 95% процентов, код скопиапщен у borisbn)
Код

std::map< std::string, int > std_m;
boost::unordered_map< std::string, int > boost_m;
stdext::hash_map< std::string, int > hash_m;

std::vector< std::string > values;

const int N = 300000;
const int STRLEN = 300;

//const int N = 300000;
//const int STRLEN = 30;

//const int N = 1000000;
//const int STRLEN = 4;



// -----------------------------------------------------
template <typename TCONT, typename TARR>
double test_insert (TCONT & cont, TARR const & arr)
{
   int t1 = clock();
   for ( int i = 0; i < N; i++ )
   {
       cont[ arr[ i ] ] = i;
   }
   int t2 = clock();
   return (t2 - t1) / (double)CLOCKS_PER_SEC * 1000;
}

// -----------------------------------------------------
template <typename TCONT, typename TARR>
double test_find (TCONT & cont, TARR const & arr)
{
   int t1 = clock();
   int res = 1;
   for ( int i = 0; i < N; i++ )
   {
       res &= cont[ arr[ i ] ];
   }
   int t2 = clock();
   return (t2 - t1) / (double)CLOCKS_PER_SEC * 1000 + res; //здесь res, чтобы не соптимизировал :) res == 0;
}

// -----------------------------------------------------
template <typename TCONT, typename TARR>
double test_find_find (TCONT & cont, TARR const & arr)
{
   int t1 = clock();
   int res = 1;
   for ( int i = 0; i < N; i++ )
   {
      res &= cont.find( arr[ i ] )->second;
   }
   int t2 = clock();
   return (t2 - t1) / (double)CLOCKS_PER_SEC * 1000 + res; //здесь res, чтобы не соптимизировал :) res == 0;;
}


// -----------------------------------------------------
int main()
{
    values.reserve (N);
    for ( int i = 0; i < N; i++ )
    {
        static const char liters [] = "0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~";
        char newstr [STRLEN+1];
        for (int j=0; j<STRLEN; ++j)
             newstr [j] = liters [rand() % (sizeof liters - 1)];
        newstr [STRLEN] = 0;
        values.push_back( newstr );
    }
    
    std::cout << "insert:" << std::endl;
    for ( int k = 0; k < 3; k++ )
    {
        std::cout << "std   : " << std::setw( 8 ) << test_insert (std_m,   values) << " ms." << std::endl;
        std::cout << "boost : " << std::setw( 8 ) << test_insert (boost_m, values) << " ms." << std::endl;
        std::cout << "hash  : " << std::setw( 8 ) << test_insert (hash_m,  values) << " ms." << std::endl << std::endl;
    }

    std::cout << std::endl;
    std::cout << "find[] :" << std::endl;
    for ( int k = 0; k < 3; k++ )
    {
        std::cout << "std   : " << std::setw( 8 ) << test_find (std_m,   values) << " ms." << std::endl;
        std::cout << "boost : " << std::setw( 8 ) << test_find (boost_m, values) << " ms." << std::endl;
        std::cout << "hash  : " << std::setw( 8 ) << test_find (hash_m,  values) << " ms." << std::endl << std::endl;
    }

    std::cout << std::endl;
    std::cout << "find.find :" << std::endl;
    for ( int k = 0; k < 3; k++ )
    {
        std::cout << "std   : " << std::setw( 8 ) << test_find_find (std_m,   values) << " ms." << std::endl;
        std::cout << "boost : " << std::setw( 8 ) << test_find_find (boost_m, values) << " ms." << std::endl;
        std::cout << "hash  : " << std::setw( 8 ) << test_find_find (hash_m,  values) << " ms." << std::endl << std::endl;
    }
}


-----------

Вывод: разные алгоритмы работы! И тип контейнера лучше подбирать на реальном, конкретном приложении.
На коротких ключах буст анордеред, безусловно хорош. Даже очень хорош!

Но на длинных, возможно стоит выбрать что-то другое...

PM MAIL   Вверх
borisbn
Дата 11.11.2011, 17:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



volatile, очень интересно... Как раз следующим этапом я собирался сделать ключ из строки...
А вот результат Вашего нашего кода (со строкой), скомпилированного minGW 4.6.2 (вместо stdext::hash_map взят std::unordered_map)
Цитата

insert:
std   :      750 ms.
boost :      719 ms.
hash  :     1156 ms.

std   :      922 ms.
boost :      359 ms.
hash  :      469 ms.

std   :      922 ms.
boost :      375 ms.
hash  :      453 ms.


find[] :
std   :      953 ms.
boost :      375 ms.
hash  :      469 ms.

std   :      953 ms.
boost :      360 ms.
hash  :      484 ms.

std   :      953 ms.
boost :      359 ms.
hash  :      469 ms.


find.find :
std   :      969 ms.
boost :      359 ms.
hash  :      469 ms.

std   :      953 ms.
boost :      375 ms.
hash  :      453 ms.

std   :      969 ms.
boost :      359 ms.
hash  :      469 ms.


Цитата(volatile @  11.11.2011,  15:13 Найти цитируемый пост)
И тип контейнера лучше подбирать на реальном, конкретном приложении.

Вывод: и компилятор тоже smile

P.S. Недавно возился со студийным hash'ем... У меня получилось, что он игнорирует последний символ в строке, т.е.
hash( "abcdefg0" ) == hash( "abcdefg1" )... м.б. это так и надо, а м.б. это глюк...

Добавлено через 2 минуты и 37 секунд
я так понял, что делить на [] и find теперь уже не нужно - это был глюк minGW 4.4.0


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
volatile
Дата 11.11.2011, 23:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 37
Всего: 85



Цитата(borisbn @  11.11.2011,  17:30 Найти цитируемый пост)
Недавно возился со студийным hash'ем... У меня получилось, что он игнорирует последний символ в строке, т.е.
hash( "abcdefg0" ) == hash( "abcdefg1" )... м.б. это так и надо, а м.б. это глюк...

Не совсем понял, как это игнорирует?
   hash_m ["abcdefg0"] = 1;
   hash_m ["abcdefg1"] = 2;
   hash_m ["abcdefg2"] = 3;
   std::cout << hash_m.size () << std::endl;
Вывод 3, т.е разные хеши.

Конкретно сами числа хешей тоже можно посмотреть, приватный метод _Hashval. Там для данных строк хеши разные (2,3,0) соответственно.

Цитата(borisbn @  11.11.2011,  17:30 Найти цитируемый пост)
 вот результат Вашего нашего кода (со строкой), скомпилированного minGW 4.6.2 (

Да, там безусловно буст рулит. (Или стд не рулит?... smile)
PM MAIL   Вверх
borisbn
Дата 11.11.2011, 23:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



не... я смотрел непосредственно ф-цию std::tr1::hash. для приведённых Вами строк она выдаст одно и то же значение. потом, конечно, map это всё разрулит


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
volatile
Дата 12.11.2011, 00:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 37
Всего: 85



Цитата(borisbn @  11.11.2011,  23:38 Найти цитируемый пост)
для приведённых Вами строк она выдаст одно и то же значение

Щас, поставил брекпоинты, и посмотрел в дебагере значения хешей.
Для приведенных строк, значения подсчитываются в следеющей процедуре (файл <xhash>)
Код

template <class _InIt>
    inline size_t _Hash_value(_InIt _Begin, _InIt _End)
    {    // hash range of elements
    size_t _Val = 2166136261U;
    while(_Begin != _End)
        _Val = 16777619U * _Val ^ (size_t)*_Begin++;
    return (_Val);
    }

Брякпоинты ставил на выходе функции.
Конкретно значения хешей, для приведенных строк: 
_Val = 3802362189
_Val = 3802362188
_Val = 3802362191


PM MAIL   Вверх
boostcoder
Дата 12.11.2011, 00:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(volatile @  12.11.2011,  00:17 Найти цитируемый пост)
_Val = 16777619U * _Val ^ (size_t)*_Begin++;

FNV-1x

в GCC этот алгоритм используется только для строковых типов.

Добавлено @ 00:42
тут специализации: http://gcc.gnu.org/git/?p=gcc.git;a=blob;f...ab4ba92;hb=HEAD
тут реализация мур-мур хеш и FNV-1: http://gcc.gnu.org/git/?p=gcc.git;a=blob;f...217bf36;hb=HEAD


Это сообщение отредактировал(а) boostcoder - 12.11.2011, 00:42
PM WWW   Вверх
volatile
Дата 12.11.2011, 00:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 37
Всего: 85



Цитата(boostcoder @  12.11.2011,  00:33 Найти цитируемый пост)
в GCC этот алгоритм используется только для строковых типов. 

boostcoder, ну здесь для разных типов тоже разные хеши. В данном случае здесь именно строки. Видимо мелкомягкие (стл правда писали не они), сперли алгоритм у линуксоидов. ...  smile 

PM MAIL   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0870 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.