c++ - top - valgrind




Как я могу создать код на C++, работающий в Linux? (8)

Вы можете использовать Valgrind со следующими параметрами

valgrind --tool=callgrind ./(Your binary)

Он будет генерировать файл с именем callgrind.out.x . Затем вы можете использовать инструмент kcachegrind для чтения этого файла. Это даст вам графический анализ вещей с результатами, например, какие из них стоят.

У меня есть приложение на C ++, работающее на Linux, которое я в процессе оптимизации. Как я могу определить, какие области моего кода работают медленно?


Для однопоточных программ вы можете использовать igprof , Ignominous Profiler: https://igprof.org/ .

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


Новые ядра (например, последние ядра Ubuntu) поставляются с новыми инструментами «perf» ( apt-get install linux-tools ) AKA perf_events .

Они поставляются с классическими пробоотборниками ( man-page ), а также с потрясающим timechart !

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


Ответ на запуск valgrind --tool=callgrind не совсем завершен без некоторых опций. Обычно мы не хотим профилировать 10 минут медленного времени запуска под Valgrind и хотим профилировать нашу программу, когда она выполняет определенную задачу.

Так я и рекомендую. Сначала запустите программу:

valgrind --tool=callgrind --dump-instr=yes -v --instr-atstart=no ./binary > tmp

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

callgrind_control -i on

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

callgrind_control -k

Теперь у нас есть файлы с именем callgrind.out. * В текущем каталоге. Для просмотра результатов профилирования используйте:

kcachegrind callgrind.out.*

В следующем окне я рекомендую щелкнуть заголовок столбца «Self», иначе он показывает, что «main ()» - это самая трудоемкая задача. «Я» показывает, сколько каждой функции само по себе занимает время, а не вместе с иждивенцами.


Это два метода, которые я использую для ускорения моего кода:

Для приложений с привязкой к процессору:

  1. Используйте профилировщик в режиме DEBUG для определения сомнительных частей вашего кода
  2. Затем переключитесь в режим RELEASE и закомментируйте сомнительные разделы вашего кода (не забудьте его ничем), пока не увидите изменения в производительности.

Для связанных приложений ввода / вывода:

  1. Используйте профилировщик в режиме RELEASE для определения сомнительных частей вашего кода.

NB

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

Для CPU причина для профилирования в режиме DEBUG заключается в том, что если вы попытались профилировать в режиме RELEASE , компилятор будет собирать математические, векторизованные циклы и встроенные функции, которые стремятся превратить ваш код в неуправляемый беспорядок после его сборки. Необратимый беспорядок означает, что ваш профилировщик не сможет четко определить, что происходит так долго, потому что сборка может не соответствовать исходному коду при оптимизации . Если вам нужна производительность (например, чувствительная к времени) режима RELEASE , отключите функции отладчика по мере необходимости, чтобы сохранить полезную производительность.

Для привязки ввода / вывода профилировщик все еще может идентифицировать операции ввода-вывода в режиме RELEASE, поскольку операции ввода-вывода либо связаны извне с общей библиотекой (в большинстве случаев), либо в худшем случае приведут к тому, (который также легко идентифицируется профилировщиком).


Это ответ на ответ Gprof от Nazgob .

Я использую Gprof последние пару дней и уже нашел три существенных ограничения, один из которых я еще не видел нигде (еще):

  1. Он не работает должным образом в многопоточном коде, если вы не используете workaround

  2. Граф вызовов путается указателями на функции. Пример. У меня есть функция multithread() которая позволяет мне многопоточность указанной функции по указанному массиву (оба передаются как аргументы). Однако Gprof рассматривает все вызовы multithread() как эквивалентные для вычисления времени, затрачиваемого на детей. Поскольку некоторые функции, которые я передаю multithread() занимают гораздо больше времени, чем другие, мои графики вызовов в основном бесполезны. (Тем, кто задается вопросом, является ли проблема с потоками: no, multithread() может быть необязательно, и в этом случае выполнял все последовательно только на вызывающем потоке).

  3. Здесь говорится, что «... цифры числа звонков выводятся путем подсчета, а не выборки. Они полностью точны ...». Тем не менее, я нахожу свой график вызовов, давая мне 5345859132 + 784984078 в качестве статистики звонка для моей самой вызываемой функции, где первым номером должны быть прямые вызовы, а также вторыми рекурсивными вызовами (которые все из себя). Поскольку это подразумевало, что у меня была ошибка, я вложил длинные (64-битные) счетчики в код и снова сделал тот же самый запуск. Мой счет: 5345859132 прямой и 78094395406 саморекурсивный вызов. Там много цифр, поэтому я укажу, что рекурсивные звонки, которые я измеряю, составляют 78 млрд, против 784 м от Gprof: коэффициент 100 раз. Оба прогона были однопоточным и неоптимизированным кодом, один скомпилированный -g и другой -pg .

Это был GNU Gprof (GNU Binutils для Debian) 2.18.0.20080103, работающий под 64-разрядным Debian Lenny, если это кому-то помогает.


Я предполагаю, что вы используете GCC. Стандартным решением было бы профилирование с помощью gprof .

Обязательно добавьте -pg для компиляции перед профилированием:

cc -o myprog myprog.c utils.c -g -pg

Я еще не пробовал, но я слышал хорошие вещи о google-perftools . Это определенно стоит попробовать.

Связанный с этим вопрос.

Несколько других слов, если gprof не выполняет эту работу для вас: Valgrind , Intel VTune , Sun DTrace .


Используйте Valgrind, callgrind и kcachegrind:

valgrind --tool=callgrind ./(Your binary)

генерирует callgrind.out.x. Прочтите его, используя kcachegrind.

Используйте gprof (add -pg):

cc -o myprog myprog.c utils.c -g -pg 

(не очень хорошо для многопоточных, указателей функций)

Использовать google-perftools:

Используется выборка времени, выявление узких мест ввода-вывода и процессора.

Intel VTune является лучшим (бесплатно для образовательных целей).

Другие: AMD Codeanalyst (с заменой на AMD CodeXL), OProfile, инструменты «perf» (apt-get install linux-tools)





profiling