2011-07-19 22 views
24

Estoy tratando de comparar la GPU con el rendimiento de la CPU. Para la GPU NVIDIA he estado utilizando los tipos cudaEvent_t para obtener un tiempo muy preciso.¿Cómo crear un temporizador de alta resolución en Linux para medir el rendimiento del programa?

Para la CPU He estado usando el siguiente código:

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

Al parecer, ese trozo de código sólo es bueno si usted está contando en cuestión de segundos. Además, los resultados en algún momento resultan bastante extraños.

¿Alguien sabe de alguna manera para crear un temporizador de alta resolución en Linux?

+0

Ver esta pregunta: http://stackoverflow.com/questions/700392/high-resolution-timing-part- of-your-code –

Respuesta

34

Consulte clock_gettime, que es una interfaz POSIX para temporizadores de alta resolución.

Si, después de leer la página de manual, uno se queda preguntándose sobre la diferencia entre CLOCK_REALTIME y CLOCK_MONOTONIC, ve Difference between CLOCK_REALTIME and CLOCK_MONOTONIC?

consulte la siguiente página para un ejemplo completo: http://www.guyrutenberg.com/2007/09/22/profiling-code-using-clock_gettime/

+0

Para que quede claro lo que leí, ¿podría darme un ejemplo de cómo usaría clock_gettime para encontrar el tiempo transcurrido en nanosegundos? – sj755

+0

@ seljuq70: He agregado un enlace a un ejemplo completo. – NPE

+0

¡Debería hacerlo gracias! – sj755

-1
+0

'clock_gettime' es preferible ya que le proporciona nanosegundos. –

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

también hay CLOCK_REALTIME_HR, pero no estoy seguro si hace alguna diferencia ..

+0

Y no estoy seguro de si 'CLOCK_REALTIME_HR' es compatible. [Pregunta] (https://stackoverflow.com/questions/46094769/clock-realtime-nanosecond-precision-support-in-kernel). – gsamaras

0

¿Le interesa el tiempo de pared (cuánto tiempo realmente pasa) o el ciclo (cuántos ciclos)? En el primer caso, debe usar algo como gettimeofday.

El temporizador de resolución más alta usa las instrucciones de ensamblaje RDTSC x86. Sin embargo, esto mide los tics del reloj, por lo que debe asegurarse de que el modo de ahorro de energía esté desactivado.

La página wiki para el CET da algunos ejemplos: http://en.wikipedia.org/wiki/Time_Stamp_Counter

+0

En una CPU moderna, 'rdtsc' correlaciona 1: 1 con la hora del reloj de pared, no con los ciclos del reloj central.No se detiene cuando el proceso (o la CPU completa) está en reposo, y se ejecuta a frecuencia constante independientemente del turbo/ahorro de energía. Use contadores de rendimiento para medir los ciclos reales del reloj central. p.ej. 'perf stat awk 'BEGIN {for (i = 0; i <10000000; i ++) {}}''. –

18

para resumir la información presentada hasta el momento, estas son las dos funciones necesarias para las aplicaciones típicas.

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

Aquí es un ejemplo de cómo utilizarlos para cronometrar el tiempo que toma para calcular la varianza de una lista de entrada.

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

¿No estás ignorando el 'tv_sec' del' timespec'? Además, ¿por qué 'CLOCK_PROCESS_CPUTIME_ID' en lugar de' CLOCK_MONOTONIC'? – amaurea

+0

El póster compara la CPU con el rendimiento de la GPU. Honestamente estás dando código para obtener el tiempo de CPU. CLOCK_PROCESS_CPUTIME_ID. Esto significa que obtendrá aceleraciones de muchos órdenes de magnitud. Para el rendimiento de la CPU/GPU (esta pregunta) siempre use el tiempo de pared. Eliminar esta respuesta – TimZaman

+1

@TimZaman Sí, en tiempo real podría ser mejor en el caso de uso del póster. Sin embargo, no voy a extraer una respuesta, obviamente la gente lo ha encontrado útil. Aclamaciones. – Alex

0

epoll IMPLEMENTACIÓN: https://github.com/ielife/simple-timer-for-c-language

uso como esto:

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); 
Cuestiones relacionadas