Таймерная функция для обеспечения времени в нано секунды с помощью C++

101
задан Peter Mortensen 14 July 2015 в 13:22
поделиться

8 ответов

То, что другие отправили о выполнении функции неоднократно в цикле, корректно.

Для Linux (и BSD) Вы хотите использовать clock_gettime () .

#include <sys/time.h>

int main()
{
   timespec ts;
   // clock_gettime(CLOCK_MONOTONIC, &ts); // Works on FreeBSD
   clock_gettime(CLOCK_REALTIME, &ts); // Works on Linux
}

окна For Вы хотите использовать QueryPerformanceCounter. И вот находится больше на QPC

, По-видимому, существует известное выпуск с QPC на некоторых чипсетах, таким образом, можно хотеть удостовериться, что у Вас нет тех чипсетом. Дополнительно некоторый двухъядерный AMDS может также вызвать проблема . См. второе сообщение sebbbi, где он заявляет:

QueryPerformanceCounter () и QueryPerformanceFrequency () предлагают немного лучшее разрешение, но имеют другие вопросы. Например, в Windows XP, весь AMD Athlon X2 двухъядерные центральные процессоры возвращают ПК любого из ядер "случайным образом" (ПК иногда переходит немного назад), если Вы особенно не устанавливаете AMD двухъядерный пакет драйвера для устранения проблемы. Мы не заметили никакого другого двойного + базовые центральные процессоры, имеющие подобные проблемы (p4 двойной, p4 ht, core2 двойной, core2 четверка, четверка явления).

РЕДАКТИРОВАНИЕ 16.07.2013:

похоже, что существует некоторое противоречие на эффективности QPC при определенных обстоятельствах, как указано в http://msdn.microsoft.com/en-us/library/windows/desktop/ee417693 (v=vs.85) .aspx

... В то время как QueryPerformanceCounter и QueryPerformanceFrequency обычно корректируются для нескольких процессоров, ошибки в BIOS или драйверах могут привести к этим стандартным программам, возвратив различные значения, когда поток перемещается от одного процессора до другого...

Однако этот ответ StackOverflow https://stackoverflow.com/a/4588605/34329 указывает, что QPC должен хорошо работать на любом MS ОС после пакета обновления XP Победы 2.

Эта статья показывает, что Windows 7 может определить, имеет ли процессор (процессоры) инвариантный TSC, и отступает к внешнему таймеру, если они не делают. http://performancebydesign.blogspot.com/2012/03/high-resolution-clocks-and-timers-for.html Синхронизация через процессоры является все еще проблемой.

Другое прекрасное чтение, связанное с таймерами:

Дополнительную информацию см. в комментариях.

83
ответ дан Community 24 November 2019 в 04:37
поделиться

Если это для Linux, я использовал функцию "gettimeofday", который возвращает структуру, которая дает секунды и микросекунды с Эпохи. Можно тогда использовать timersub для вычитания двух, чтобы получить разницу во времени и преобразовать его в любую точность времени, которое Вы хотите. Однако Вы определяете наносекунды, и это похоже на функцию , clock_gettime () - то, что Вы ищете. Это помещает время с точки зрения секунд и наносекунд в структуру, которую Вы передаете в него.

2
ответ дан Will Mc 24 November 2019 в 04:37
поделиться

При необходимости в подвторой точности Вы должны использовать определенные для системы расширения и должны будете свериться с документацией для операционной системы. POSIX поддерживает до микросекунд с gettimeofday, но ничто более точное, так как компьютеры не имели частот выше 1 ГГц.

при использовании Повышения можно проверить повышение:: posix_time.

3
ответ дан Raymond Martineau 24 November 2019 в 04:37
поделиться

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

, Например, если Вы оцениваете, Ваша функция могла бы взять 800 нс, чтобы выполнить, назвать его в цикле десятью миллионами раз (который тогда займет приблизительно 8 секунд). Разделите общее время на десять миллионов для получения времени на вызов.

5
ответ дан Greg Hewgill 24 November 2019 в 04:37
поделиться

Я использую следующее для получения желаемых результатов:

#include <time.h>
#include <iostream>
using namespace std;

int main (int argc, char** argv)
{
    // reset the clock
    timespec tS;
    tS.tv_sec = 0;
    tS.tv_nsec = 0;
    clock_settime(CLOCK_PROCESS_CPUTIME_ID, &tS);
    ...
    ... <code to check for the time to be put here>
    ...
    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tS);
    cout << "Time taken is: " << tS.tv_sec << " " << tS.tv_nsec << endl;

    return 0;
}
22
ответ дан iammilind 24 November 2019 в 04:37
поделиться

С тем уровнем точности было бы лучше рассуждать в галочке ЦП, а не в системном вызове как часы () . И не забывайте, что, если требуется больше чем одна наносекунда для выполнения инструкции... имеющей точность наносекунды, в значительной степени невозможно.

однако, что-то как этот является запуском:

Вот фактический код для получения количества 80x86, галочки тактовой частоты ЦП передали, так как ЦП был в последний раз запущен. Это будет работать над Pentium и выше (386/486 не поддерживаемый). Этот код является на самом деле конкретным Visual C++ MS, но может быть, вероятно, очень легок портированный к тому, что, пока это поддерживает встроенный ассемблерный код.

inline __int64 GetCpuClocks()
{

    // Counter
    struct { int32 low, high; } counter;

    // Use RDTSC instruction to get clocks count
    __asm push EAX
    __asm push EDX
    __asm __emit 0fh __asm __emit 031h // RDTSC
    __asm mov counter.low, EAX
    __asm mov counter.high, EDX
    __asm pop EDX
    __asm pop EAX

    // Return result
    return *(__int64 *)(&counter);

}

Эта функция имеет также преимущество того, чтобы быть чрезвычайно быстрым - обычно требуется не больше, чем 50 циклов CPU для выполнения.

Используя иллюстрации Синхронизации :
, Если необходимо перевести количества часов в истинное прошедшее время, разделите результаты на тактовую частоту микросхемы. Помните, что "расчетный" GHz, вероятно, будет немного отличаться от действительной скорости Вашей микросхемы. Для проверки истинной скорости микросхемы можно использовать несколько очень хороших утилит или вызов Win32, QueryPerformanceFrequency ().

27
ответ дан 2 revs, 2 users 85% 24 November 2019 в 04:37
поделиться

Можно использовать следующую функцию с gcc, работающим под x86 процессорами:

unsigned long long rdtsc()
{
  #define rdtsc(low, high) \
         __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))

  unsigned int low, high;
  rdtsc(low, high);
  return ((ulonglong)high << 32) | low;
}

с Цифровым C++ Марса:

unsigned long long rdtsc()
{
   _asm
   {
        rdtsc
   }
}

, который читает высокопроизводительный таймер на микросхеме. Я использую это при выполнении профилирования.

5
ответ дан Blaisorblade 24 November 2019 в 04:37
поделиться

Чтобы сделать это правильно, вы можете использовать один из двух способов: либо RDTSC, либо clock_gettime(). Второй способ примерно в 2 раза быстрее и имеет то преимущество, что дает правильное абсолютное время. Обратите внимание, что для корректной работы RDTSC нужно использовать как указано (другие комментарии на этой странице содержат ошибки, и могут давать неверные значения времени на некоторых процессорах)

inline uint64_t rdtsc()
{
    uint32_t lo, hi;
    __asm__ __volatile__ (
      "xorl %%eax, %%eax\n"
      "cpuid\n"
      "rdtsc\n"
      : "=a" (lo), "=d" (hi)
      :
      : "%ebx", "%ecx" );
    return (uint64_t)hi << 32 | lo;
}

и для clock_gettime: (я выбрал микросекундное разрешение произвольно)

#include <time.h>
#include <sys/timeb.h>
// needs -lrt (real-time lib)
// 1970-01-01 epoch UTC time, 1 mcs resolution (divide by 1M to get time_t)
uint64_t ClockGetTime()
{
    timespec ts;
    clock_gettime(CLOCK_REALTIME, &ts);
    return (uint64_t)ts.tv_sec * 1000000LL + (uint64_t)ts.tv_nsec / 1000LL;
}

полученное время и значения:

Absolute values:
rdtsc           = 4571567254267600
clock_gettime   = 1278605535506855

Processing time: (10000000 runs)
rdtsc           = 2292547353
clock_gettime   = 1031119636
23
ответ дан 24 November 2019 в 04:37
поделиться