STL Альтернатива

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

Я программист игры, и это было проблемой во многих проектах, над которыми я работал. Довольно сложно получить 60 кадров в секунду, когда вы используете контейнер STL для всего.

Я использую MSVC для большей части моей работы.

14 ответов

EASTL возможен, но все еще не совершенен. Пол Педриана из Electronic Arts провел исследование различных реализаций STL с точки зрения производительности в игровых приложениях, краткое изложение которых можно найти здесь: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2271.html

Некоторые из этих изменений рассматриваются для включения в стандарт C++.

И обратите внимание, даже EASTL не оптимизируется для неоптимизированного случая. У меня был файл Excel с некоторым временем, но я думаю, что потерял его, но для доступа это было что-то вроде:

       debug   release
STL      100        10
EASTL     10         3
array[i]   3         1

Самый большой успех, который я имел, катал мои собственные контейнеры. Вы можете понизить их производительность почти до массива [x].

Мой опыт показывает, что хорошо спроектированный код STL работает медленно в отладочных сборках, потому что оптимизатор выключен. Контейнеры STL генерируют много вызовов конструкторам и оператору =, который (если они имеют малый вес) вставляется / удаляется в сборках релиза.

Кроме того, в Visual C++ 2005 и более поздних версиях включена проверка STL в сборках выпуска и отладки. Это огромный скачок производительности для STL-тяжелого программного обеспечения. Его можно отключить, определив _SECURE_SCL=0 для всех ваших модулей компиляции. Обратите внимание, что наличие разных состояний _SECURE_SCL в разных блоках компиляции почти наверняка приведет к катастрофе.

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

Если вы используете визуальные студии, вы можете рассмотреть следующие вопросы:

#define _SECURE_SCL 0
#define _HAS_ITERATOR_DEBUGGING 0

Это только для итераторов, какой тип операций STL вы выполняете? Возможно, вы захотите взглянуть на оптимизацию операций с памятью; то есть, используя resize() для вставки нескольких элементов одновременно вместо использования pop/push для вставки элементов по одному.

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

Я говорю о реальной разработке игр здесь.

Держу пари, что ваш STL использует проверенную реализацию для отладки. Это, вероятно, хорошая вещь, поскольку она будет перехватывать итераторы и тому подобное. Если для вас это большая проблема, возможно, есть переключатель компилятора, который отключит его. Проверьте свои документы.

Если вы используете Visual C++, вы должны взглянуть на это:

http://channel9.msdn.com/shows/Going+Deep/STL-Iterator-Debugging-and-Secure-SCL/

и ссылки с этой страницы, которые покрывают различные затраты и опции всей проверки режима отладки, которую выполняет MS/Dinkware STL.

Если вы собираетесь задать такой зависимый от платформы вопрос, было бы неплохо упомянуть и вашу платформу...

Извините, я не могу оставить комментарий, поэтому вот ответ: EASTL теперь доступен на github: https://github.com/paulhodge/EASTL

Проверьте EASTL.

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

Еще одна вещь, которая может вас заинтересовать, заключается в том, что ваши "сборка отладки" и "сборка выпуска", вероятно, включают в себя изменение (как минимум) 4 настроек, которые имеют слабую связь.

  1. Создание файла.pdb (cl /Zi и link /DEBUG), который позволяет проводить символьную отладку. Вы можете добавить /OPT:ref к параметрам компоновщика; компоновщик удаляет функции без ссылок, когда не создает файл.pdb, но в режиме / DEBUG он сохраняет их все (так как символы отладки ссылаются на них), если вы не добавите это явно.
  2. Использование отладочной версии библиотеки времени выполнения C (возможно, MSVCR*D.dll, но это зависит от используемой среды выполнения). Это сводится к /MT или /MTd (или что-то еще, если не использовать среду выполнения DLL)
  3. Отключение оптимизации компилятора (/Od)
  4. установка препроцессора #defines DEBUG или NDEBUG

Они могут быть переключены независимо. Первый ничего не стоит в производительности во время выполнения, хотя он добавляет размер. Вторая делает ряд функций более дорогими, но оказывает огромное влияние на malloc и free; версии отладочной среды стараются "отравить" память, к которой они обращаются, значениями, чтобы очистить неинициализированные ошибки данных. Я полагаю, что с реализациями MSVCP* STL это также устраняет все пулы выделения, которые обычно выполняются, так что утечки показывают именно тот блок, который вы думаете, а не какой-то больший кусок памяти, который он перераспределяет; это означает, что он делает больше вызовов malloc поверх них намного медленнее. Третий; хорошо, что каждый делает много вещей (у этого вопроса есть некоторое хорошее обсуждение предмета). К сожалению, это необходимо, если вы хотите, чтобы пошаговый режим работал плавно. Четвертый затрагивает множество библиотек различными способами, но наиболее заметным является то, что он компилируется или удаляет assert() и друзей.

Таким образом, вы можете рассмотреть возможность построения с некоторой меньшей комбинацией этих выборов. Я часто использую сборки, которые используют символы (/Zi и link / DEBUG) и утверждения (/DDEBUG), но все еще оптимизированы (/O1 или /O2 или любые другие используемые вами флаги), но с указателями фрейма стека, сохраненными для очистить трассировки (/Oy-) и использовать обычную библиотеку времени выполнения (/MT). Это работает близко к моей сборке релиза и является полуотлаживаемым (обратные трассировки хороши, пошаговое выполнение немного странно на уровне исходного кода; уровень сборки, конечно, работает нормально). Вы можете иметь сколько угодно конфигураций; просто клонируйте свой первый релиз и включите те части отладки, которые кажутся полезными.

Как насчет библиотеки ACE? Это объектно-ориентированная среда с открытым исходным кодом для программного обеспечения для одновременной коммуникации, но она также имеет несколько контейнерных классов.

Извлечение структур данных и алгоритмов с объектно-ориентированными шаблонами проектирования в C++. Бруно Прайсс http://www.brpreiss.com/

Ultimate++ имеет собственный набор контейнеров - не уверен, что вы можете использовать их отдельно от остальной части библиотеки: http://www.ultimatepp.org/

Qt переопределил большинство стандартных библиотек C++ с различными интерфейсами. Это выглядит довольно хорошо, но это может быть дорого для коммерческой версии.

Изменить: С тех пор Qt был выпущен под LGPL, что обычно позволяет использовать его в коммерческом продукте, не покупая коммерческую версию (которая также существует).

Контейнеры STL не должны запускаться "очень медленно" при отладке или где-либо еще. Возможно, вы их неправильно используете. Вы не сталкиваетесь с чем-то вроде ElectricFence или Valgrind в отладке? Они замедляют все, что делает много распределений.

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

Также существует ETL https://www.etlcpp.com/. Эта библиотека предназначена специально для критичных по времени (детерминированных) приложений.

С веб-страницы:

ETL предназначен не для полной замены STL, а для его дополнения. Его цель дизайна охватывает четыре основные области.

  • Создайте набор контейнеров, размер или максимальный размер которого определяется во время компиляции. Эти контейнеры должны быть в значительной степени эквивалентны контейнерам, поставляемым в STL, с совместимым API.
  • Быть совместимым с C++ 03, но реализовывать как можно больше дополнений C++ 11.
  • Обладают детерминированным поведением.
  • Добавьте другие полезные компоненты, которых нет в стандартной библиотеке.

Встроенная библиотека шаблонов была разработана для встраиваемых приложений с ограниченными ресурсами. Он определяет набор контейнеров, алгоритмов и утилит, некоторые из которых имитируют части STL. Нет динамического распределения памяти. Библиотека не использует кучу. Все контейнеры (кроме навязчивых типов) имеют фиксированную емкость, позволяющую определить все выделение памяти во время компиляции. Библиотека предназначена для любого компилятора, поддерживающего C++03.

Другие вопросы по тегам