Подтвердить что ты не робот

Как анализировать время выполнения программы

Я пытаюсь оптимизировать производительность программы на С++ и сократить время ее выполнения. Тем не менее, мне трудно понять, где узкое место.

Команда времени

показывает, что сама программа занимает около 5 минут, а около 5 минут время пользовательского процессора составляет 4,5 минуты.

Профилировщик CPU (как gcc-профилировщик, так и google perftool) показывает, что вызов функции занимает всего 60 секунд в CPU. Я также попытался использовать профилировщик для выборки реального времени вместо времени процессора, и это дает мне аналогичные результаты.

Профилировщик ввода/вывода (я использовал ioapps) также показывает, что ввод/вывод занимает около 30 секунд времени работы программы.

Таким образом, в основном у меня есть 3,5 минуты (самая большая часть времени работы программы), пропавших без вести, и я считаю, что именно там есть узкое место.

Что мне не хватало, и как мне узнать, где это время?

4b9b3361

Ответ 1

Как предложил Öö Tiib, просто разбейте программу в отладчике. То, как я это делаю, это запустить программу, переключиться в окно вывода, набрать Ctrl-C, чтобы прервать программу, переключиться обратно в окно GDB, ввести "поток 1", чтобы быть в контексте основной программы, и введите "bt", чтобы увидеть трассировку стека.

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

Если вы сделаете это несколько раз, вы увидите, какая именно строка отвечает за узкое место. Как только вы увидите это на двух (2) образцах, вы пригвоздили его. Затем исправьте его и сделайте все это, найдя следующее узкое место и так далее. Вы можете легко обнаружить, что вы получаете огромное ускорение таким образом.

< пламя >

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

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

Как насчет вопроса о небольшом или большом количестве образцов? Не лучше? Хорошо, предположим, что у вас бесконечный цикл, или, если не бесконечный, он работает намного дольше, чем вы знаете, что нужно? Будет ли 1000 образцов стека найти его лучше, чем один образец? (Нет.) Если вы посмотрите на него под отладчиком, вы знаете, что находитесь в цикле, потому что он занимает в основном 100% времени. Это где-то в стеке - просто сканируйте стек, пока не найдете его. Даже если цикл занимает всего 50% или 20% времени, вероятность того, что каждый образец увидит его. Итак, если вы видите что-то, что вы могли бы избавиться от всего лишь двух образцов, стоит это сделать. Итак, что вы покупаете 1000 образцов?

Может быть, кто-то думает: "Так что, если мы пропустим проблему или две? Возможно, это достаточно хорошо". Ну, так? Предположим, что у кода есть три проблемы P, занимающие 50% времени, Q - 25%, а R - 12,5%. Хороший материал называется А. Это показывает ускорение, которое вы получаете, если вы исправите один из них, два из них или все три из них.

PRPQPQPAPQPAPRPQ original time with avoidable code P, Q, and R all mixed together
RQQAQARQ         fix P           - 2 x   speedup
PRPPPAPPAPRP     fix Q           - 1.3 x    "
PPQPQPAPQPAPPQ   fix R           - 1.14 x   "
RAAR             fix P and Q     - 4 x      "
QQAQAQ           fix P and R     - 2.7 x    "
PPPPAPPAPP       fix Q and R     - 1.6 x    "
AA               fix P, Q, and R - 8 x   speedup

Означает ли это, почему те, кто "уходит", действительно больно? Лучшее, что вы можете сделать, если вы пропустите любой, в два раза медленнее.

Их легко найти, если вы исследуете образцы. P находится на половине образцов. Если вы исправите P и сделаете это снова, Q будет на половине образцов. Как только вы исправите Q, R будет на половине образцов. Fix R, и у вас есть 8-кратное ускорение. Вам не нужно останавливаться на достигнутом. Вы можете продолжать идти, пока вы действительно не найдете ничего, чтобы исправить.

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

Есть хорошие профилировщики. Лучшие из них - это стековые сэмплеры на стенах, которые сообщают инклюзивный процент в отдельных строках, позволяя вам включать и отключать выборку с помощью горячей клавиши. Zoom (wiki) является таким профилировщиком.

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

</Пламя >