2012-04-11 5 views
6

Можно создать дубликат:
C++ string::find complexityПроизводительность станд :: strstr vs. станд :: строка :: найти

Недавно я узнал, что функция std::string::find является порядок медленнее чем функция std::strstr - в моей среде с GCC 4.7 на Linux. Разница в производительности зависит от длины строк и от аппаратной архитектуры.

Однако есть веская причина для разницы: std::string::find в основном вызывает std::memcmp в цикле - с временной сложностью O(m * n). Напротив, std::strstr высоко оптимизирован для архитектуры оборудования (например, с инструкциями SSE) и использует более сложный алгоритм сопоставления строк (по-видимому, Knuth-Morris-Pratt).

Я также был удивлен, когда не нашел сложностей во времени этих двух функций в языковых документах (т. Е. Чертежах N3290 и N1570). Я только нашел временные сложности для char_traits. Но это не помогает, потому что нет функции для поиска подстроки в char_traits.

Я бы ожидал, что std::strstr и memmem содержат аналогичные оптимизации с почти одинаковой производительностью. И до недавнего времени я предполагал, что std::string::find использует memmem внутренне.

Вопросов: Есть ли хорошая причина, почему std::string::find не использует std::memmem? И отличается ли это от другой реализации?

Вопрос не в следующем: Какова наилучшая реализация этой функции? На C++ действительно сложно спорить, если он медленнее C. Я бы не имел значения, будут ли обе реализации медленными. Это разница в производительности, которая действительно болит.

+0

@FrerichRaabe: Вы правы, есть несколько совпадений в двух вопросах. Но мои вопросы более конкретны, а другая статья не отвечает ни одному из них. – nosid

+0

@ nosid: да. Посмотрите, в частности, на дополнительное объяснение в комментариях dietmar kuhl о среднем случае против наихудшего случая и сложности пространства, почему это, скорее всего, не используется. Эти аргументы не изменяются, если вы повторно используете 'std :: memmem' и реализуете алгоритм с нуля. – KillianDS

ответ

2

Во-первых, что такое memmem? Я не могу найти это в стандарте C++, а также в стандарте Posix (который содержит все стандартные функции C).

Во-вторых, любые значения измерений будут зависеть от фактических данных. Использование КМП, например, будет пессимизировать во многих случаях; вероятно, в большинстве случаев, когда используются функции-члены от std::string; время для установки необходимых таблиц часто будет больше, чем общее время алгоритма прямого доступа. Такие вещи, как O(m*n) , не имеют большого значения, когда типичная длина строки коротка.

+0

Я осел, что 'memmem' является частью C, но, видимо, это не так. 'memmem' является' strstr', что 'memcmp' относится к' strcmp'. Однако я уверен, что вы это знаете. Тем не менее, как я уже упоминал несколько раз. Вопрос не в том, является ли KMP хорошим выбором.Вопрос в том, почему они используют совершенно разные алгоритмы для 'strstr' и' std :: string :: find'. – nosid

+0

@nosid Возможно, потому что ожидаемый шаблон использования отличается? Или потому, что разные авторы имеют привилегированные разные шаблоны использования? В большинстве приложений, которые я видел, большинство строк довольно короткие, причем самые длинные строки соответствуют, возможно, строке. Для таких строк использование чего-то вроде KMP, вероятно, было бы пессимизацией. Если авторы 'memmem' думали, что типичный пример использования будет включать в себя блоки с несколькими КБ памяти или больше, с другой стороны, это определенно стоит. –

+0

Согласно моим оценкам, по состоянию на 25.06.2013: для GCC строка :: find немного быстрее (~ 10%) (x86_64, -march = native, работает на AWS) - для MSVC 2, раз медленнее (x86, SSE2 , на рабочем столе AMD). (полная оптимизация) – Etherealone

Смежные вопросы