Когда linear search быстрее hash map
От: c-smile Канада http://terrainformatica.com
Дата: 15.10.17 23:58
Оценка: 4 (2) :)
Эта вот дискуссия
Автор: c-smile
Дата: 05.10.17
подвигла мя на написание статьи на тему.

Приводится случай когда O(N) lookup кроет O(1) как бык овцу. А над O(log N) — вообще сплошное надругательство.

Не ходите дети в Африку гулять используйте std::map не по назначению.
Отредактировано 16.10.2017 5:38 c-smile . Предыдущая версия .
Re: Когда linear search быстрее hash map
От: MTD https://github.com/mtrempoltsev
Дата: 16.10.17 07:18
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Приводится случай когда O(N) lookup кроет O(1) как бык овцу[/url].


Поэтому Кнута и ко надо читать с осторожностью — хоть парни и толковые, но инфа несколько устарела, если не учитывать устройство современного процессора (всякие кеши, предсказание переходов), то можно легко напороться на то, что алгоритм с худшей асимптоматикой внезапно уделывает алгоритм с хорошей. Ну и вообще стоит прикидывать стоимость операций — внезапно может оказаться, что при вставке на небольшом массиве со сдвигом, чтобы сохранить упорядоченность и бинарный поиск, уделывают деревья только так.
Re: Когда linear search быстрее hash map
От: fin_81  
Дата: 16.10.17 07:29
Оценка:
Здравствуйте, c-smile, Вы писали:

#if ENTRIES > 4
...
#if ENTRIES > 5
...
#if ENTRIES > 6
...
#if ENTRIES > 7
...
#if ENTRIES > 8
...
#if ENTRIES > 9
...
#endif
#endif
#endif
#endif
#endif
#endif

Бобер, выдыхай!

По теме, без комментариев.
Re: Когда linear search быстрее hash map
От: MTD https://github.com/mtrempoltsev
Дата: 16.10.17 07:31
Оценка: +1
Здравствуйте, c-smile, Вы писали:

CS>Приводится случай когда O(N) lookup кроет O(1) как бык овцу. А над O(log N) — вообще сплошное надругательство.


А если еще с этим сравнить, то это еще быстрей будет:

switch (*str++)
{
case 'p':
    switch (*str++)
    {
    case 'o':
        if (length == 4 && *str++ == 'r' && *str++ == 't')
        {
            ...
        }
        break;
    case 'u':
        if (length == 9 && *str++ == 'b' && *str++ == 'l' && *str++ == 'i' && *str++ == 'c' && *str++ == 'K' && *str++ == 'e' && *str++ == 'y')
        {
            ...
        }
        break;
    }
    break;
}


Но и это еще не все, ведь можно сравнивать не по байту, а сразу по 4, например.
Re: Когда linear search быстрее hash map
От: Engler Беларусь  
Дата: 16.10.17 07:34
Оценка: +2
Здравствуйте, c-smile, Вы писали:

Если честно, я бы присмотрелся к Вашему тесту более внимательно.

1. Например, настораживает передача строки по значению.
FormatterType t2e(std::string s) { ... }


2. В контейнерах, std::map / std::unordered_map вы храните объекты std::string,
в то время когда в функция if_t2e сравнение идет с использованием обертки slice.

3. Дальше, маленькие объемы + еще std::string тот случай, когда нужно быть особенно внимательным,
поэтому еще нужно посмотреть как компилятор работает со строками ( какие там оптимизации ),
вполне возможно что разные компиляторы дадут разный результат.

4. Различные реализации std::hash / std::equal_to / std::less для std::string могут дать разные результат.

5. Можно попробовать хранить const char* вместо std::string, возможно тоже покажет другой результат.

И.т.д.
Re: Когда linear search быстрее hash map
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 16.10.17 07:41
Оценка: +2
Здравствуйте, c-smile, Вы писали:

CS>Приводится случай когда O(N) lookup кроет O(1) как бык овцу.


В полтора раза (3.44 против 2.13) это "как бык овцу"?
"Ну извините..." ((с) Вовочка)
И заметим, всего-то при 9 записях линейный поиск уже хуже мапы. А что дальше?

CS> А над O(log N) — вообще сплошное надругательство.


Аж на пару десятков процентов.

Нет, тут понятно, что std::map обычно медленнее std::unordered_map (если не слишком дорого вычислять хэш), но Ваш пример как раз _против_ того, чтобы тут был выбран линейный поиск по умолчанию.
Потому что какая-то мапа тут по природе вещей и хорошо масштабируется, а замена на линейный поиск будет типичной преждевременной оптимизацией со всеми своими последствиями. Если это место станет узким и будет гарантия неувеличения количества ключевых строк — тогда можно сократить до линейного поиска. Если хотя бы одно условие не выполняется — закат солнца вручную отменяется.

А если тут нужен действительно быстрый поиск — то как это делать — смотреть, например, в Kamailio:

#define _acce_ 0x65636361   /* "acce" */
#define _allo_ 0x6f6c6c61   /* "allo" */
#define _auth_ 0x68747561   /* "auth" */
#define _oriz_ 0x7a69726f   /* "oriz" */
#define _atio_ 0x6f697461   /* "atio" */
#define _call_ 0x6c6c6163   /* "call" */
#define __id2_ 0x2064692d   /* "-id " */
#define __id1_ 0x3a64692d   /* "-id:" */

[...]

#define FIRST_QUATERNIONS       \
        case _via1_: via1_CASE; \
        case _from_: from_CASE; \
        case _to12_: to12_CASE; \
        case _cseq_: cseq_CASE; \
        case _call_: call_CASE; \
        case _cont_: cont_CASE; \
        case _rout_: rout_CASE; \
        case _max__: max_CASE;  \


ну и так далее — строка нарезается стандартными порциями по 4 байта, переводится к нижнему регистру (SIP заголовки — case-insensitive) и затем задача компилятора — выбрать правильный вариант разложить case (обычно он строит что-то вроде дерева). Да, это очень жёсткая целевая оптимизация. Но там она оправдана.

CS>Не ходите дети в Африку гулять используйте std::map не по назначению.


Вы не показали, на каком количестве значений std::map эффективнее линейного поиска. Это уже некрасиво.
И VS-only code тоже сейчас как-то "не очень".
The God is real, unless declared integer.
Re: Когда linear search быстрее hash map
От: Vain Россия google.ru
Дата: 16.10.17 07:46
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Не ходите дети в Африку гулять используйте std::map не по назначению.

Игра в бирюльки по сравнению с оптимизацией критического по времени кода через интринсики, форсинлайн, гоуту и т.д..
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re: Когда linear search быстрее hash map
От: rg45 СССР  
Дата: 16.10.17 07:56
Оценка: +4
Здравствуйте, c-smile, Вы писали:

CS>Приводится случай когда O(N) lookup кроет O(1) как бык овцу. А над O(log N) — вообще сплошное надругательство.


Так ведь никто и не обещал, что O(1) ВСЕГДА будет быстрее O(log N), а O(log N) ВСЕГДА быстрее O(N). Потому, что все эти оценки задают лишь асимптотику зависимости времени выполнения от размера входной последовательности, но не являются точной зависимостью. Они позволяют лишь говорить о том, что существует такой размер входной последовательности, свыше которого O(1) начинает выигрывать у O(log N), а O(log N) у O(N). А вот каким будет этот размер, зависит уже от...
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 16.10.2017 8:15 rg45 . Предыдущая версия .
Re[2]: Когда linear search быстрее hash map
От: samius Япония http://sams-tricks.blogspot.com
Дата: 16.10.17 08:10
Оценка: +2
Здравствуйте, MTD, Вы писали:

MTD>Здравствуйте, c-smile, Вы писали:


CS>>Приводится случай когда O(N) lookup кроет O(1) как бык овцу[/url].


MTD>Поэтому Кнута и ко надо читать с осторожностью — хоть парни и толковые, но инфа несколько устарела, если не учитывать устройство современного процессора (всякие кеши, предсказание переходов), то можно легко напороться на то, что алгоритм с худшей асимптоматикой внезапно уделывает алгоритм с хорошей.

Асимптотика описывает поведение при стремлении переменной к чему-то. В применении к сложностям алгоритмов рассматривается характер поведения при увеличении переменной, или стремлении к бесконечности. Кроме того, O(f(n)) — это верхняя оценка по определению, которая лишь указывает что существует константа и такое n0, что рост сложности алгоритма при n >= n0 будет соответствовать некоторой модели с точностью до этих констант. То есть, асимптотика не предназначена для описывания нижних оценок на малых n.

Причем Кнут — не понятно. Он не утверждает обратного.
Re: Когда linear search быстрее hash map
От: so5team https://stiffstream.com
Дата: 16.10.17 08:19
Оценка: 9 (2)
Здравствуйте, c-smile, Вы писали:

CS>Эта вот дискуссия
Автор: c-smile
Дата: 05.10.17
подвигла мя на написание статьи на тему.


CS>Приводится случай когда O(N) lookup кроет O(1) как бык овцу. А над O(log N) — вообще сплошное надругательство.


CS>Не ходите дети в Африку гулять используйте std::map не по назначению.


Пару лет назад столкнулись с похожей историей. Посмотрели, как ведут себя разные структуры данных для хранения подписок агентов в зависимости от количества этих самых подписок. Оказалось, что если подписок всего один-два десятка, то хранение подписок в std::vector и простой линейный перебор по нему работает эффективнее всего. Если количество подписок находится в районе от пары десятков до пары сотен, то эффективнее работает std::map. А вот от 200+ подписок -- самым эффективным оказывается std::unordered_map.
Re[3]: Когда linear search быстрее hash map
От: MTD https://github.com/mtrempoltsev
Дата: 16.10.17 08:47
Оценка: +1
Здравствуйте, samius, Вы писали:

S>То есть, асимптотика не предназначена для описывания нижних оценок на малых n.


Речь не только про малые n.

S>Причем Кнут — не понятно.


При том, что Кнут не учитывал, как алгоритмы выполняются на современном железе, такая теория в вакууме. Знать надо, но каждый раз надо думать, а слепо верить в О.

S>Он не утверждает обратного.


Для оценки скорости алгоритмов предлагается использовать его асиптотику — это не всегда верно. Например, у бинарного дерева и упорядоченного массива асимптотика поиска одинакова — логарифм. Значит ли это, что они одинаково эффективны? Нет, ведь дерево может быть размазано по памяти из-за этого возникнут постоянные промахи в кеш и упорядоченный массив окажется в разы эффективней. Рассматривается это у Кнута? Нет, вот о том и речь.
Re: Когда linear search быстрее hash map
От: uzhas Ниоткуда  
Дата: 16.10.17 08:55
Оценка: -3
Здравствуйте, c-smile, Вы писали:

CS>Эта вот дискуссия
Автор: c-smile
Дата: 05.10.17
подвигла мя на написание статьи на тему.

ты, к сожалению, не понял, что та дискуссия совсем не производительность, а про качество кода
тебе даже форматтер кода намекнул об этом

CS>Приводится случай когда O(N) lookup кроет O(1) как бык овцу. А над O(log N) — вообще сплошное надругательство.

бенчмарки хороши тем, что можно любое решение засунуть в топ, а неудобные цифры просто не публиковать

CS>Не ходите дети в Африку гулять используйте std::map не по назначению.


сам-то понял, что сказал? (с)

у меня для тебя плохие новости: назначение мапы быть ассоциативным контейнером, то есть хранить ключи и значения и искать по ключам
ты хоть выводы может внятно сформулировать? вот сортировка пузырьком тоже в топ иногда выходит, но выводы из этого надо ещё уметь сделать
Re[4]: Когда linear search быстрее hash map
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 16.10.17 09:17
Оценка: +3
Здравствуйте, MTD, Вы писали:

S>>Причем Кнут — не понятно.


MTD>При том, что Кнут не учитывал, как алгоритмы выполняются на современном железе, такая теория в вакууме. Знать надо, но каждый раз надо думать, а слепо верить в О.


Я бы сказал "каждый раз надо измерять", а не "думать". "Думать" оно надо, но не это ключевое.

А "неучёт на современном железе" это специфика не только Кнута. Я навскидку сейчас посмотрел Кормена, Сиену, Седжвика — нигде не упоминается — по крайней мере нет ни в оглавлении, ни в предметном указателе. Поэтому следует полагать, что им в пару обязательно читать "Computer achitecture: a quantitative approach" или аналог.

Ещё Вы почему-то распространяете паразитную логическую связь "алгоритмы, сложность -> Кнут". Кнут — фундамент и историческая база, но сейчас его использовать в качестве абсолюта уже поздновато.

S>>Он не утверждает обратного.


MTD>Для оценки скорости алгоритмов предлагается использовать его асиптотику — это не всегда верно. Например, у бинарного дерева и упорядоченного массива асимптотика поиска одинакова — логарифм. Значит ли это, что они одинаково эффективны? Нет, ведь дерево может быть размазано по памяти из-за этого возникнут постоянные промахи в кеш и упорядоченный массив окажется в разы эффективней. Рассматривается это у Кнута? Нет, вот о том и речь.


Реальный мир надо всегда учитывать. Где-то алгоритм в 100 раз быстрее на RAM, но в 2 раза прожорливее по объёму памяти затормозится из-за трэшинга свопа. Где-то очень эффективная обычно сортировка станет вдруг медленнее пузырька из-за того, что сравнение в 1000 раз дороже обмена.

Вы читая Кнута почему-то смотрите только на выводы, а не на проведённый им анализ. А ведь то, чему он учит — это именно анализировать от основ. И при всём при этом не знаете никого, кроме Кнута... просто пугаете этим.
The God is real, unless declared integer.
Re[5]: Когда linear search быстрее hash map
От: MTD https://github.com/mtrempoltsev
Дата: 16.10.17 09:20
Оценка: -2 :)
Здравствуйте, netch80, Вы писали:

N>Вы читая Кнута почему-то смотрите только на выводы, а не на проведённый им анализ. А ведь то, чему он учит — это именно анализировать от основ. И при всём при этом не знаете никого, кроме Кнута...


Телепатам привет!

N>просто пугаете этим.


Шапочка из фольги спасет от голосов в голове и вернет душевное здоровье.
Re[4]: Когда linear search быстрее hash map
От: samius Япония http://sams-tricks.blogspot.com
Дата: 16.10.17 10:34
Оценка: +1
Здравствуйте, MTD, Вы писали:

MTD>Здравствуйте, samius, Вы писали:


S>>То есть, асимптотика не предназначена для описывания нижних оценок на малых n.


MTD>Речь не только про малые n.

Но таки про нижние оценки?

S>>Причем Кнут — не понятно.


MTD>При том, что Кнут не учитывал, как алгоритмы выполняются на современном железе, такая теория в вакууме. Знать надо, но каждый раз надо думать, а слепо верить в О.

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

S>>Он не утверждает обратного.


MTD>Для оценки скорости алгоритмов предлагается использовать его асиптотику — это не всегда верно.

Это не так. Асимптотику предлагается использовать для прогноза роста стоимости алгоритма при увеличении n. При том, что M и x0 неизвестны, как об этом и указал Кнут.

MTD>Например, у бинарного дерева и упорядоченного массива асимптотика поиска одинакова — логарифм. Значит ли это, что они одинаково эффективны? Нет, ведь дерево может быть размазано по памяти из-за этого возникнут постоянные промахи в кеш и упорядоченный массив окажется в разы эффективней. Рассматривается это у Кнута? Нет, вот о том и речь.

Речь тут ровно о том, что вы сделали неверную оценку и прогноз. Неверно выбрали M и x0 при оценке скорости работы алгоритмов на дереве в условиях постоянных промахов. Нет никаких оснований утверждать на одинаковую эффективность алгоритмов с одной асимптотикой, не зная констант. Именно об этом Кнут и писал.
Re: Когда linear search быстрее hash map
От: kov_serg Россия  
Дата: 16.10.17 12:54
Оценка: 6 (1)
Здравствуйте, c-smile, Вы писали:

CS>Эта вот дискуссия
Автор: c-smile
Дата: 05.10.17
подвигла мя на написание статьи на тему.


CS>Приводится случай когда O(N) lookup кроет O(1) как бык овцу. А над O(log N) — вообще сплошное надругательство.


А какой дикий восторг у них вызовет, что сортированный массив может в разы быстрее обрабатываться чем тот же но не сортированный.
    Without std::sort(data, data + arraySize);, the code runs in 11.54 seconds.
    With the sorted data, the code runs in 1.93 seconds.
Re: Когда linear search быстрее hash map
От: Mr.Delphist  
Дата: 16.10.17 13:26
Оценка: +1
Здравствуйте, c-smile, Вы писали:



CS>Эта вот дискуссия
Автор: c-smile
Дата: 05.10.17
подвигла мя на написание статьи на тему.


CS>Приводится случай когда O(N) lookup кроет O(1) как бык овцу. А над O(log N) — вообще сплошное надругательство.


Ну, это не новость давно уже. "Умелки" процессора, размер кэшей, характер данных, их расклад в памяти и прочие вроде бы мелочи способны смешать с грязью самые теоретически-лучшие алгоритмы.
Re[2]: Когда linear search быстрее hash map
От: Erop Россия  
Дата: 16.10.17 13:57
Оценка: +1
Здравствуйте, MTD, Вы писали:

MTD>Здравствуйте, c-smile, Вы писали:


CS>>Приводится случай когда O(N) lookup кроет O(1) как бык овцу[/url].


MTD>Поэтому Кнута и ко надо читать <...> внезапно может оказаться, что при вставке на небольшом массиве со сдвигом, чтобы сохранить упорядоченность и бинарный поиск, уделывают деревья только так.


1) Дык потому структуры вроде B-tree и придумали...
2) У того Кнута, которого когда-то читал я, было прямо написано, что какой бы распрекрасный рекурсивный алгоритм с очень хорошей асимптотикой вы не придумали, обычно начиная с некоторого размера и меньше, надо переключаться на что-то быстрое на маленьких данных
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: Когда linear search быстрее hash map
От: Erop Россия  
Дата: 16.10.17 14:02
Оценка: 22 (1) +1
Здравствуйте, so5team, Вы писали:

S>Пару лет назад столкнулись с похожей историей. Посмотрели, как ведут себя разные структуры данных для хранения подписок агентов в зависимости от количества этих самых подписок. Оказалось, что если подписок всего один-два десятка, то хранение подписок в std::vector и простой линейный перебор по нему работает эффективнее всего. Если количество подписок находится в районе от пары десятков до пары сотен, то эффективнее работает std::map. А вот от 200+ подписок -- самым эффективным оказывается std::unordered_map.



Можно было сделать B-tree на 10-20 подписок на узел, -- совместило бы достоинства разных подходов...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: Когда linear search быстрее hash map
От: c-smile Канада http://terrainformatica.com
Дата: 16.10.17 15:35
Оценка:
Здравствуйте, MTD, Вы писали:

MTD>А если еще с этим сравнить, то это еще быстрей будет:


Я про это тоже написал. Это примерно то что генерирует perfect hash (gperf).
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.