Профилирование C ++ при наличии агрессивного встраивания? - PullRequest
17 голосов
/ 18 января 2010

Я пытаюсь выяснить, где моя программа на С ++ проводит свое время, используя gprof. Вот моя дилемма: если я компилирую с теми же настройками оптимизации, которые я использую для своей сборки выпуска, почти все становится встроенным, и gprof бесполезно говорит мне, что 90% моего времени тратится в основной подпрограмме, где все встроено. С другой стороны, если я компилирую с отключенным встраиванием, программа будет работать на порядок медленнее.

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

Я использую 64-разрядную версию Ubuntu 9.04 на четырехъядерном компьютере Intel. Я посмотрел в google-perftools, но на x86_64 это не очень хорошо работает. Запуск на 32-битном компьютере не возможен.

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

Редактировать: Вот некоторые разъяснения моей проблемы. Я прошу прощения, если это не было ясно изначально.

Я хочу найти, где время проводилось в моей заявке. Профилирование моей оптимизированной сборки привело к тому, что gprof сказал мне, что ~ 90% времени тратится на main, где все было встроено. Я уже знал это до профилирования!

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

Вкратце: есть ли способ получить полезную информацию о профилировании программы C ++ без отключения отключения оптимизации или встраивания?

Ответы [ 6 ]

9 голосов
/ 18 января 2010

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

Вот довольно полное объяснение того, как это сделать.

Вы можете сделать это вручную или использовать один из профилировщиков, который может предоставить ту же информацию, например oprofile и RotateRight / Zoom .

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

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

2 голосов
/ 18 января 2010

Будет ли valgrind более полезным?

В сочетании с KCachegrind GUI он предлагает бесплатный и простой способ просмотра аннотированного кода, подходящего для встроенного кода. Здесь у вас есть довольно простая инструкция: http://web.stanford.edu/class/cs107/guide_callgrind.html

2 голосов
/ 18 января 2010

Вы можете использовать более мощный профилировщик, такой как Intel VTune, который может дать вам уровень детализации производительности сборочной линии.

http://software.intel.com/en-us/intel-vtune/

Это для Windows и Linux, но стоит денег ...

2 голосов
/ 18 января 2010

Разработайте несколько макросов, используя высокопроизводительный механизм синхронизации вашего ЦП (например, x86 ) - подпрограммы, которые не зависят от системных вызовов, и привязывают один поток, выполняющий цикл ядра, определенный процессор ( установить сходство ). Вам нужно будет реализовать следующие макросы.

PROF_INIT //allocate any variables -- probably a const char
PROF_START("name") // start a timer
PROF_STOP() // end a timer and calculate the difference -- 
            // which you write out using a async fd

У меня было что-то подобное, что я поместил в каждую интересующую меня функцию, я убедился, что макрос поместил синхронизирующие вызовы в контекст дерева вызовов - это, возможно, самый точный способ для профилирования.

Примечание:

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

- редактировать -

Возможно, вас заинтересует ссылка из этого ответа на один из моих вопросов .

0 голосов
/ 18 января 2010

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

0 голосов
/ 18 января 2010

Неважно, что код работает медленнее (кроме вашего удобства, конечно) - профилировщик все равно сообщит вам правильную пропорцию времени, потраченного на каждую функцию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...