Как вычислить время выполнения фрагмента кода в C++

PIC18:

переполнение

    PUSH   
    CALL   overflow 
118
задан Yu Hao 3 August 2014 в 13:09
поделиться

7 ответов

Вы можете использовать эту функцию, которую я написал. Вы вызываете GetTimeMs64 () , и он возвращает количество миллисекунд, прошедших с эпохи unix с использованием системных часов - точно так же, как time (NULL) , за исключением миллисекунд.

Он работает как в Windows, так и в Linux; это потокобезопасный.

Обратите внимание, что степень детализации для окон составляет 15 мс; в Linux это зависит от реализации, но обычно это также 15 мс.

#ifdef _WIN32
#include <Windows.h>
#else
#include <sys/time.h>
#include <ctime>
#endif

/* Remove if already defined */
typedef long long int64; typedef unsigned long long uint64;

/* Returns the amount of milliseconds elapsed since the UNIX epoch. Works on both
 * windows and linux. */

uint64 GetTimeMs64()
{
#ifdef _WIN32
 /* Windows */
 FILETIME ft;
 LARGE_INTEGER li;

 /* Get the amount of 100 nano seconds intervals elapsed since January 1, 1601 (UTC) and copy it
  * to a LARGE_INTEGER structure. */
 GetSystemTimeAsFileTime(&ft);
 li.LowPart = ft.dwLowDateTime;
 li.HighPart = ft.dwHighDateTime;

 uint64 ret = li.QuadPart;
 ret -= 116444736000000000LL; /* Convert from file time to UNIX epoch time. */
 ret /= 10000; /* From 100 nano seconds (10^-7) to 1 millisecond (10^-3) intervals */

 return ret;
#else
 /* Linux */
 struct timeval tv;

 gettimeofday(&tv, NULL);

 uint64 ret = tv.tv_usec;
 /* Convert from micro seconds (10^-6) to milliseconds (10^-3) */
 ret /= 1000;

 /* Adds the seconds (10^0) after converting them to milliseconds (10^-3) */
 ret += (tv.tv_sec * 1000);

 return ret;
#endif
}
115
ответ дан 24 November 2019 в 01:57
поделиться

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

Оберните ваши вызовы таймера для соответствующей системы. Для Windows QueryPerformanceCounter довольно быстр и «безопасен» в использовании.

Вы можете использовать «rdtsc» на любом современном ПК с X86, но могут возникнуть проблемы на некоторых многоядерных машинах (переключение ядра может изменить таймер) или если у вас включен какой-то шаг-шаг.

2
ответ дан 24 November 2019 в 01:57
поделиться

Я предлагаю использовать стандартные библиотечные функции для получения информации о времени из системы.

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

2
ответ дан 24 November 2019 в 01:57
поделиться

У меня есть еще один рабочий пример, который использует микросекунды (UNIX , POSIX и т. Д.)

    #include <sys/time.h>
    typedef unsigned long long timestamp_t;

    static timestamp_t
    get_timestamp ()
    {
      struct timeval now;
      gettimeofday (&now, NULL);
      return  now.tv_usec + (timestamp_t)now.tv_sec * 1000000;
    }

    ...
    timestamp_t t0 = get_timestamp();
    // Process
    timestamp_t t1 = get_timestamp();

    double secs = (t1 - t0) / 1000000.0L;

Вот файл, в котором мы это закодировали:

https://github.com/arhuaco/junkcode/blob/master/emqbit-bench/bench.c

43
ответ дан 24 November 2019 в 01:57
поделиться

Windows предоставляет функцию QueryPerformanceCounter (), а Unix имеет gettimeofday () Обе функции могут измерять разницу минимум в 1 микросекунду.

5
ответ дан 24 November 2019 в 01:57
поделиться

Оператор запятой привязывается ниже назначения, поэтому выражение

inhi=1,0

задает для inhi значение 1 , а затем возвращает 0 . Аналогично

inhi=0,1

набор inhi - 0 и возвращает 1 . Все это эквивалентно

if(y[0] > y[1]) {
   inhi = 1;
   ihi = 0;
} else {
   inhi = 0;
   ihi = 1;
}

Я бы предложил переписать так, если можно. inhi и ihi , по-видимому, имеют одну и ту же цель (в этом утверждении), и сочетание троичного оператора (?: ) и оператора запятой, которое вы имеете, дает им различный вес.

-121--2681514-

Это означает следующее:

if (y[0]>y[1])
{
    inhi = 1;
    ihi = 0;
} else {
    inhi = 0;
    ihi = 1;
}

Или написанный другим способом (в C++):

inhi = (y[0]>y[1]);
ini = !inhi;
-121--2681513-

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

(ссылка выше на французскую страницу википедии, но она имеет образцы кода C++, английская версия - здесь )

3
ответ дан 24 November 2019 в 01:57
поделиться

boost :: timer , вероятно, даст вам столько точности, сколько вам нужно. Это далеко не так точно, чтобы сказать вам, сколько времени займет a = a + 1; , но, мне кажется, зачем вам нужно рассчитывать время для того, что занимает пару наносекунд?

0
ответ дан 24 November 2019 в 01:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: