Что именно измеряет профилирование C++ (инструменты производительности процессора Google)?
-
05-07-2019 - |
Вопрос
Я пытаюсь начать работу с Google Perf Tools для профилирования некоторых приложений, интенсивно использующих процессор.Это статистический расчет, который записывает каждый шаг в файл с использованием ofstream.Я не эксперт по C++, поэтому мне сложно найти узкое место.Мой первый проход дает результаты:
Total: 857 samples 357 41.7% 41.7% 357 41.7% _write$UNIX2003 134 15.6% 57.3% 134 15.6% _exp$fenv_access_off 109 12.7% 70.0% 276 32.2% scythe::dnorm 103 12.0% 82.0% 103 12.0% _log$fenv_access_off 58 6.8% 88.8% 58 6.8% scythe::const_matrix_forward_iterator::operator* 37 4.3% 93.1% 37 4.3% scythe::matrix_forward_iterator::operator* 15 1.8% 94.9% 47 5.5% std::transform 13 1.5% 96.4% 486 56.7% SliceStep::DoStep 10 1.2% 97.5% 10 1.2% 0x0002726c 5 0.6% 98.1% 5 0.6% 0x000271c7 5 0.6% 98.7% 5 0.6% _write$NOCANCEL$UNIX2003
Это удивительно, поскольку все реальные вычисления происходят в SliceStep::DoStep.«_write$UNIX2003» (где я могу узнать, что это такое?), похоже, возникает при записи выходного файла.Меня смущает то, что если я закомментирую все outfile << "text"
заявлений и запустить ппроф, 95% находится в SliceStep::DoStep
и `_write$UNIX2003' исчезнет.Однако мое приложение не ускоряется по общему времени.Все это ускоряется менее чем на 1 процент.
Что мне не хватает?
Добавлен:Вывод pprof без outfile <<
заявления это:
Total: 790 samples 205 25.9% 25.9% 205 25.9% _exp$fenv_access_off 170 21.5% 47.5% 170 21.5% _log$fenv_access_off 162 20.5% 68.0% 437 55.3% scythe::dnorm 83 10.5% 78.5% 83 10.5% scythe::const_matrix_forward_iterator::operator* 70 8.9% 87.3% 70 8.9% scythe::matrix_forward_iterator::operator* 28 3.5% 90.9% 78 9.9% std::transform 26 3.3% 94.2% 26 3.3% 0x00027262 12 1.5% 95.7% 12 1.5% _write$NOCANCEL$UNIX2003 11 1.4% 97.1% 764 96.7% SliceStep::DoStep 9 1.1% 98.2% 9 1.1% 0x00027253 6 0.8% 99.0% 6 0.8% 0x000274a6
Это похоже на то, что я ожидал, за исключением того, что я не вижу видимого увеличения производительности (0,1 секунды при 10-секундном расчете).Код по сути:
ofstream outfile("out.txt");
for loop:
SliceStep::DoStep()
outfile << 'result'
outfile.close()
Обновлять:Я рассчитываю время, используя boost::timer, начиная с того места, где начинается профилировщик, и заканчивая там, где он заканчивается.Я не использую нитки или что-то необычное.
Решение
Из моих комментариев:
Цифры, которые вы получаете от своего профилировщика, говорят, что без операторов печати программа должна работать примерно на 40% быстрее.
Однако время выполнения остается почти таким же.
Очевидно, что одно из измерений должно быть неправильным.Это означает, что вам придется проводить больше и более качественные измерения.
Сначала я предлагаю начать с другого простого инструмента:команда времени.Это должно дать вам примерное представление о том, на что тратится ваше время.
Если результаты все еще не окончательны, вам нужен лучший тестовый пример:
- Используйте большую проблему
- Перед измерением сделайте разминку.Сделайте несколько циклов и затем начните любые измерения (в том же процессе).
Тиристан:Это все в пользователе.Я думаю, то, что я делаю, довольно просто...Означает ли что-нибудь тот факт, что файл все время открыт?
Это означает, что профилировщик ошибается.
Вывод 100000 строк на консоль с помощью Python приводит к чему-то вроде:
for i in xrange(100000):
print i
Утешить:
time python print.py
[...]
real 0m2.370s
user 0m0.156s
sys 0m0.232s
Против:
time python test.py > /dev/null
real 0m0.133s
user 0m0.116s
sys 0m0.008s
Моя точка зрения такова:Ваши внутренние измерения и время показывает, что вы ничего не получите от отключения вывода.Google Perf Tools говорит, что вам следует это сделать.Кто не прав?
Другие советы
_write$UNIX2003, вероятно, относится к write
Системный вызов POSIX, который выводит данные на терминал.Ввод-вывод очень медленный по сравнению с чем-либо еще, поэтому имеет смысл, что ваша программа проводит там много времени, если вы пишете достаточно много вывода.
Я не уверен, почему ваша программа не ускорится, если вы удалите вывод, но я не могу сделать предположение только на основе предоставленной вами информации.Было бы неплохо увидеть часть кода или даже вывод perftools после удаления оператора cout.
Google perftools собирает образцы стека вызовов, поэтому вам нужно получить представление о них.
Согласно документу, вы можете отображать граф вызовов с точностью до оператора или адреса.Это должно сказать вам то, что вам нужно знать.