2011-07-19 23 views
24

Próbuję porównać GPU do wydajności procesora. W przypadku procesora graficznego NVIDIA używam typów cudaEvent_t, aby uzyskać bardzo precyzyjny timing.Jak utworzyć zegar o wysokiej rozdzielczości w systemie Linux, aby mierzyć wydajność programu?

Dla CPU Używam następujący kod:

// 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; 

Widocznie, że fragment kodu jest tylko dobra, jeśli liczysz w sekundach. Poza tym wyniki czasami wydają się dość dziwne.

Czy ktoś wie, w jaki sposób utworzyć zegar wysokiej rozdzielczości w systemie Linux?

+0

Zobacz na to pytanie: http://stackoverflow.com/questions/700392/high-resolution-timing-part- of-your-code –

Odpowiedz

34

Sprawdź interfejs clock_gettime, który jest interfejsem POSIX dla timerów o wysokiej rozdzielczości.

Jeżeli po przeczytaniu manpage, jesteś zastanawiać, o różnicy między CLOCK_REALTIME i CLOCK_MONOTONIC patrz Difference between CLOCK_REALTIME and CLOCK_MONOTONIC?

zobacz następującą stronę, aby uzyskać pełną przykład: http://www.guyrutenberg.com/2007/09/22/profiling-code-using-clock_gettime/

+0

Po prostu mam jasne o tym, co przeczytałem, możesz dać mi przykład, w jaki sposób chcesz użyć clock_gettime, aby znaleźć czas, który upłynął w nanosekundach? – sj755

+0

@ seljuq70: Dodałem link do pełnego przykładu. – NPE

+0

To powinno zrobić to dzięki! – sj755

-1
+0

'clock_gettime' jest preferowany, ponieważ dostajesz nanosekundy. –

1
struct timespec t; 
clock_gettime(CLOCK_REALTIME, &t); 

istnieje również CLOCK_REALTIME_HR, ale nie jestem pewien, czy to robi jakąkolwiek różnicę ..

+0

I nie jestem pewien, czy 'CLOCK_REALTIME_HR' jest obsługiwany. [Pytanie] (https://stackoverflow.com/questions/46094769/clock-realtime-nanosecond-precision-support-in-kernel). – gsamaras

0

Czy interesuje Cię czas muru (ile czasu faktycznie upływa) lub liczba cykli (ile cykli)? W pierwszym przypadku powinieneś użyć czegoś takiego jak gettimeofday.

Zegar o najwyższej rozdzielczości korzysta z instrukcji montażu RDTSC x86. Jednakże mierzy to taktowanie zegara, więc powinieneś być pewien, że tryb oszczędzania energii jest wyłączony.

stronę wiki dla TSC podaje kilka przykładów: http://en.wikipedia.org/wiki/Time_Stamp_Counter

+0

Na nowoczesnym CPU, 'rdtsc' koreluje 1: 1 z czasem zegarowym, a nie rdzeniowym.Nie zatrzymuje się, gdy proces (lub cały procesor) jest w trybie uśpienia i działa ze stałą częstotliwością, niezależnie od trybu turbo/oszczędzania energii. Użyj liczników wydajności do mierzenia rzeczywistych cykli zegara rdzeniowego. na przykład 'perf stat awk 'BEGIN {for (i = 0; i <10000000; i ++) {}}''. –

18

Aby podsumować informacje przedstawione do tej pory, to są dwie funkcje wymagane dla typowych zastosowań.

#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; 
} 

Oto przykład użycia ich do określenia czasu trwania obliczenia wariancji listy danych wejściowych.

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); 
+6

Nie ignorujesz 'tv_sec' z' timespec'? Również dlaczego 'CLOCK_PROCESS_CPUTIME_ID' zamiast' CLOCK_MONOTONIC'? – amaurea

+0

Plakat porównuje wydajność procesora z GPU. Uczciwie podajesz kod pobierający czas procesora. CLOCK_PROCESS_CPUTIME_ID. Oznacza to, że dostanie prędkości o wiele rzędów wielkości. Dla wydajności CPU/GPU (to pytanie) zawsze używaj czasu ściany. Usuń tę odpowiedź. – TimZaman

+1

@TimZaman Tak, w czasie rzeczywistym może być lepiej w przypadku użycia plakatu. Nie zamierzam jednak odpowiadać, oczywiście ludzie uznali to za przydatne. Twoje zdrowie. – Alex

0

epoll implementacja: https://github.com/ielife/simple-timer-for-c-language

stosowanie tak:

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); 
Powiązane problemy