Что именно измеряет профилирование C++ (google cpu perf tools)?

Я пытаюсь начать работу с Google Perf Tools для профилирования некоторых приложений, интенсивно использующих процессор. Это статистический расчет, который выводит каждый шаг в файл, используя `ofstream'. Я не эксперт по C++, поэтому мне трудно найти узкое место. Мой первый проход дает результаты:

Всего: 857 образцов
     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% косы:: dnorm
     103 12,0% 82,0% 103 12,0% _log$fenv_access_off
      58   6,8% 88,8% 58 6,8% косы::const_matrix_forward_iterator::operator*
      37   4,3% 93,1%       37   4,3% косы::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" заявления и запустить pprof, 95% находится в SliceStep::DoStep и `_write$UNIX2003'исчезает. Тем не менее, мое приложение не ускоряется, если судить по общему времени. Все это ускоряется менее чем на 1 процент.

Что мне не хватает?

Добавлено: вывод pprof без outfile << заявления это:

Всего: 790 образцов 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% косу:: dnorm 83 10,5% 78,5% 83 10,5% косу:: const_matrix_forward_iterator:: оператор *
      70   8,9% 87,3% 70 8,9% косы::matrix_forward_iterator::operator*
      28   3,5% 90,9% 78 9,9% std:: трансформация 26 3,3%  94,2% 26 3,3% 0x00027262
      12   1,5% 95,7% 12 1,5% _ писать $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, начиная с начала профилировщика и заканчивая там, где он заканчивается. Я не использую темы или что-нибудь необычное.

3 ответа

Решение

Из моих комментариев:

Цифры, которые вы получаете от своего профилировщика, говорят, что программа должна быть примерно на 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 говорит, что вы должны. Кто не прав?

Google perftools собирает образцы стека вызовов, поэтому вам нужно немного разобраться в них.

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

_write$UNIX2003, вероятно, относится к write Системный вызов POSIX, который выводит на терминал. Ввод / вывод очень медленный по сравнению с чем-либо еще, поэтому имеет смысл, что ваша программа тратит там много времени, если вы пишете довольно много информации.

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

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