Тестирование производительности приложения на C ++ - PullRequest
6 голосов
/ 28 апреля 2009

Я пытаюсь найти способ проверить, сколько времени занимает выполнение блока кода C ++. Я использую его для сравнения кода с разными алгоритмами и на разных языках, поэтому в идеале мне бы хотелось время в секундах / миллисекундах. В Java я использую что-то вроде этого:

long startTime = System.currentTimeMillis();

function();

long stopTime = System.currentTimeMillis();
long elapsedTime = stopTime - startTime; 

Есть ли хороший способ получить точное время, подобное этому, в C ++ (или я должен использовать некоторые другие способы сравнительного анализа)?

Ответы [ 14 ]

9 голосов
/ 28 апреля 2009

Используйте лучший счетчик, доступный на вашей платформе, используйте портативность во времени (). Я использую QueryPerformanceCounter, но вижу комментарии в другом ответе.

Общие советы:

Внутренний цикл должен работать как минимум примерно в 20 раз быстрее, чем разрешение ваших часов, чтобы ошибка разрешения составляла <5%. (поэтому при использовании time () ваш внутренний цикл должен работать не менее 20 секунд) </p>

Повторите эти измерения, чтобы увидеть, соответствуют ли они.

Я использую дополнительный внешний цикл , работающий десять раз и игнорирующий самое быстрое и самое медленное измерение для вычисления среднего и отклонения. Отклонение удобно при сравнении двух реализаций: если у вас один алгоритм, принимающий 2,0 мс +/- 5, а другой 2,2 +/- 0,5, то разница не будет существенной, чтобы назвать одну из них «более быстрой». (Макс и мин все еще должны отображаться). Так что ИМХО правильное измерение производительности должно выглядеть примерно так:

10000 x 2.0 +/- 0.2 ms (min = 1.2, , max=12.6), 10 repetitions

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

Однако это не без пифалов. Чем «стабильнее» измерение, тем менее оно реалистично. Любая реализация будет сильно меняться со временем, в зависимости от состояния данных и кэша команд. Я ленив здесь, используя значение max = для оценки штрафа за первый запуск, этого может быть недостаточно для некоторых сценариев.

8 голосов
/ 28 апреля 2009

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

В одном измерении могут преобладать события ОС или другие случайные помехи.

5 голосов
/ 28 апреля 2009

Рассматривали ли вы на самом деле использование профилировщика? Visual Studio Team System имеет один встроенный, но есть и другие, такие как VTune и GlowCode.

См. Также Какой самый лучший бесплатный профилировщик C ++ для Windows?

5 голосов
/ 28 апреля 2009

В Windows вы можете использовать высокопроизводительные счетчики для получения более точных результатов:

Вы можете использовать функцию QueryPerformanceFrequency(), чтобы получить число высокочастотных тиков в секунду, а пользователю - QueryPerformanceCounter() до и после функции, которую вы хотите синхронизировать.

Конечно, этот метод не является переносимым ...

3 голосов
/ 29 апреля 2009

Что не так с clock() и CLOCKS_PER_SEC? Они стандартные C89.

Что-то вроде (прозвище из MSDN):

   long i = 6000000L;
   clock_t start, finish;
   double  duration;

   // Measure the duration of an event.
   printf( "Time to do %ld empty loops is ", i );
   start = clock();
   while( i-- ) 
      ;
   finish = clock();
   duration = (double)(finish - start) / CLOCKS_PER_SEC;
   printf( "%2.1f seconds\n", duration );
2 голосов
/ 24 января 2014

ОБЗОР

Я написал для этого простой семантический взлом.

  • Простота в использовании
  • Код выглядит аккуратно.

MACRO

#include <time.h>

#ifndef SYSOUT_F
#define SYSOUT_F(f, ...)      _RPT1( 0, f, __VA_ARGS__ ) // For Visual studio
#endif

#ifndef speedtest__             
#define speedtest__(data)   for (long blockTime = NULL; (blockTime == NULL ? (blockTime = clock()) != NULL : false); SYSOUT_F(data "%.9fs", (double) (clock() - blockTime) / CLOCKS_PER_SEC))
#endif

* 1019 USAGE *

speedtest__("Block Speed: ")
{
    // The code goes here
}

OUTPUT

Block Speed: 0.127000000s
2 голосов
/ 29 апреля 2009

Если вы хотите проверить свою производительность, вам следует подумать об измерении времени процессора , а не времени реального , которое вы пытаетесь измерить сейчас. В противном случае вы можете получить довольно неточные значения, если какое-либо другое приложение, работающее в фоновом режиме, решит выполнить некоторые тяжелые вычисления одновременно. Нужные вам функции: GetProcessTimes в Windows и getrusage в Linux.

Также вам следует рассмотреть возможность использования профилировщиков, как предлагали другие люди.

2 голосов
/ 28 апреля 2009

Я всегда использую boost :: timer или boost :: progress_timer .

psudo-код:

#include <boost/timer.hpp>

boost::timer t;

func1();
cout << "fun1: " << t.elapsed();

t.restart();
func2();
cout << "func2(): " << t.elapsed();
2 голосов
/ 28 апреля 2009

Вы можете использовать функцию time(), чтобы получить таймер с разрешением в одну секунду. Если вам нужно больше разрешения, вы можете использовать gettimeofday(). Разрешение зависит от вашей операционной системы и библиотеки времени выполнения.

0 голосов
/ 08 апреля 2011

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

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