Как создать таймер высокого разрешения в Linux для измерения производительности программы?
Я пытаюсь сравнить GPU с производительностью процессора. Для NVIDIA GPU я использую cudaEvent_t
типы, чтобы получить очень точные сроки.
для процессора я использую следующий код:
// Timers
clock_t start, stop;
float elapsedTime = 0;
// Capture the start time
start = clock();
// Do something here
.......
// Capture the stop time
stop = clock();
// Retrieve time elapsed in milliseconds
elapsedTime = (float)(stop - start) / (float)CLOCKS_PER_SEC * 1000.0f;
по-видимому, этот кусок кода хорош, только если вы считаете в секундах. Кроме того, результаты иногда получаются довольно странными.
кто-нибудь знает, как создать таймер высокого разрешения в Linux?
6 ответов
проверить clock_gettime
, который является интерфейсом POSIX для таймеров высокого разрешения.
Если, прочитав manpage, вы оставили интересно о разнице между CLOCK_REALTIME
и CLOCK_MONOTONIC
см. разница между CLOCK_REALTIME и CLOCK_MONOTONIC?
полный пример см. На следующей странице:http://www.guyrutenberg.com/2007/09/22/profiling-code-using-clock_gettime/
#include <iostream>
#include <time.h>
using namespace std;
timespec diff(timespec start, timespec end);
int main()
{
timespec time1, time2;
int temp;
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time1);
for (int i = 0; i< 242000000; i++)
temp+=temp;
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time2);
cout<<diff(time1,time2).tv_sec<<":"<<diff(time1,time2).tv_nsec<<endl;
return 0;
}
timespec diff(timespec start, timespec end)
{
timespec temp;
if ((end.tv_nsec-start.tv_nsec)<0) {
temp.tv_sec = end.tv_sec-start.tv_sec-1;
temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec;
} else {
temp.tv_sec = end.tv_sec-start.tv_sec;
temp.tv_nsec = end.tv_nsec-start.tv_nsec;
}
return temp;
}
чтобы суммировать информацию, представленную до сих пор, это две функции, необходимые для типичных приложений.
#include <time.h>
// call this function to start a nanosecond-resolution timer
struct timespec timer_start(){
struct timespec start_time;
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start_time);
return start_time;
}
// call this function to end a timer, returning nanoseconds elapsed as a long
long timer_end(struct timespec start_time){
struct timespec end_time;
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end_time);
long diffInNanos = (end_time.tv_sec - start_time.tv_sec) * (long)1e9 + (end_time.tv_nsec - start_time.tv_nsec);
return diffInNanos;
}
вот пример того, как использовать их во времени, сколько времени требуется для вычисления дисперсии списка входных данных.
struct timespec vartime = timer_start(); // begin a timer called 'vartime'
double variance = var(input, MAXLEN); // perform the task we want to time
long time_elapsed_nanos = timer_end(vartime);
printf("Variance = %f, Time taken (nanoseconds): %ld\n", variance, time_elapsed_nanos);
struct timespec t;
clock_gettime(CLOCK_REALTIME, &t);
существует также CLOCK_REALTIME_HR, но я не уверен, имеет ли это какое-либо значение..
вас интересует время стены (сколько времени на самом деле проходит) или количество циклов (сколько циклов)? В первом случае, вы должны использовать что-то вроде gettimeofday
.
самый высокий таймер разрешения использует RDTSC
x86 инструкция по сборке. Однако это измеряет тики часов, поэтому вы должны быть уверены, что режим энергосбережения отключен.
страница wiki для TSC дает несколько примеров:http://en.wikipedia.org/wiki/Time_Stamp_Counter
epoll implemention: https://github.com/ielife/simple-timer-for-c-language
использовать такой:
timer_server_handle_t *timer_handle = timer_server_init(1024);
if (NULL == timer_handle) {
fprintf(stderr, "timer_server_init failed\n");
return -1;
}
ctimer timer1;
timer1.count_ = 3;
timer1.timer_internal_ = 0.5;
timer1.timer_cb_ = timer_cb1;
int *user_data1 = (int *)malloc(sizeof(int));
*user_data1 = 100;
timer1.user_data_ = user_data1;
timer_server_addtimer(timer_handle, &timer1);
ctimer timer2;
timer2.count_ = -1;
timer2.timer_internal_ = 0.5;
timer2.timer_cb_ = timer_cb2;
int *user_data2 = (int *)malloc(sizeof(int));
*user_data2 = 10;
timer2.user_data_ = user_data2;
timer_server_addtimer(timer_handle, &timer2);
sleep(10);
timer_server_deltimer(timer_handle, timer1.fd);
timer_server_deltimer(timer_handle, timer2.fd);
timer_server_uninit(timer_handle);