2009-01-20 8 views
72

¿Cuál es la mejor manera de sincronizar una sección de código con alta resolución y portabilidad?¿Mejor método de sincronización en C?

/* Time from here */ 
ProcessIntenseFunction(); 
/* to here. */ 

printf("Time taken %d seconds %d milliseconds", sec, msec); 

¿Hay una biblioteca estándar que tenga una solución multiplataforma?

Respuesta

120

creo que esto debería funcionar:

#include <time.h> 

clock_t start = clock(), diff; 
ProcessIntenseFunction(); 
diff = clock() - start; 

int msec = diff * 1000/CLOCKS_PER_SEC; 
printf("Time taken %d seconds %d milliseconds", msec/1000, msec%1000); 
+10

Esto es realmente bueno ya que le da tiempo de CPU en lugar de tiempo transcurrido (tiempo transcurrido podría verse afectada por otros procesos). Solo tenga en cuenta que una cifra de 10 segundos no significa necesariamente que se ejecutará en un tiempo transcurrido de 10 segundos, ya que puede haber consideraciones de E/S. Esto mide la CPU ** SOLAMENTE **. – paxdiablo

+1

Lo usé cientos de veces y es la mejor/más fácil solución para esta pregunta – Gerhard

+0

¿cuál es la resolución de tiempo del reloj()? y por qué diff * 1000? –

19

gettimeofday() probablemente haga lo que quiera.

Si tiene hardware Intel, a continuación le mostramos cómo leer el contador de instrucciones en tiempo real de la CPU. Le indicará la cantidad de ciclos de CPU ejecutados desde que se inició el procesador. Este es probablemente el contador más alto y de grano más fino que puede obtener para medir el rendimiento.

Tenga en cuenta que este es el número de ciclos de la CPU. En Linux, puede obtener la velocidad de CPU de/proc/cpuinfo y dividir para obtener el número de segundos. Convertir esto a un doble es bastante útil.

Cuando ejecuto esto en mi caja, me sale

 
11867927879484732 
11867927879692217 
it took this long to call printf: 207485 

Aquí está la Intel developer's guide que da un montón de detalles.

#include <stdio.h> 
#include <stdint.h> 

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

main() 
{ 
    unsigned long long x; 
    unsigned long long y; 
    x = rdtsc(); 
    printf("%lld\n",x); 
    y = rdtsc(); 
    printf("%lld\n",y); 
    printf("it took this long to call printf: %lld\n",y-x); 
} 
0

de alta resolución es relativo ... yo estaba buscando en los ejemplos y la mayoría se abastecen de milisegundos. Sin embargo, para mí es importante medir microsegundos. No he visto una solución independiente de plataforma para microsegundos y pensé que sería útil algo como el siguiente código. Estaba sincronizando en Windows por el momento y lo más probable es que agregue una implementación gettimeofday() al hacer lo mismo en AIX/Linux.

#ifdef WIN32 
     #ifndef PERFTIME 
     #include <windows.h> 
     #include <winbase.h> 
     #define PERFTIME_INIT unsigned __int64 freq; QueryPerformanceFrequency((LARGE_INTEGER*)&freq); double timerFrequency = (1.0/freq); unsigned __int64 startTime; unsigned __int64 endTime; double timeDifferenceInMilliseconds; 
     #define PERFTIME_START QueryPerformanceCounter((LARGE_INTEGER *)&startTime); 
     #define PERFTIME_END QueryPerformanceCounter((LARGE_INTEGER *)&endTime); timeDifferenceInMilliseconds = ((endTime-startTime) * timerFrequency); printf("Timing %fms\n",timeDifferenceInMilliseconds); 
    #define PERFTIME(funct) {unsigned __int64 freq; QueryPerformanceFrequency((LARGE_INTEGER*)&freq); double timerFrequency = (1.0/freq); unsigned __int64 startTime; QueryPerformanceCounter((LARGE_INTEGER *)&startTime); unsigned __int64 endTime; funct; QueryPerformanceCounter((LARGE_INTEGER *)&endTime); double timeDifferenceInMilliseconds = ((endTime-startTime) * timerFrequency); printf("Timing %fms\n",timeDifferenceInMilliseconds);} 
     #endif 
    #else 
     //AIX/Linux gettimeofday() implementation here 
    #endif 

Uso:

PERFTIME(ProcessIntenseFunction()); 

or 

PERFTIME_INIT 
PERFTIME_START 
ProcessIntenseFunction() 
PERFTIME_END 
0

Si no desea que el tiempo de CPU, entonces creo que lo que estás buscando es la estructura timeval.

utilizo el siguiente para calcular el tiempo de ejecución:

int timeval_subtract(struct timeval *result,                                   
        struct timeval end,                                     
        struct timeval start)                                    
{                                             
     if (start.tv_usec < end.tv_usec) {                                   
       int nsec = (end.tv_usec - start.tv_usec)/1000000 + 1;                            
       end.tv_usec -= 1000000 * nsec;                                  
       end.tv_sec += nsec;                                     
     }                                           
     if (start.tv_usec - end.tv_usec > 1000000) {                                 
       int nsec = (end.tv_usec - start.tv_usec)/1000000;                             
       end.tv_usec += 1000000 * nsec;                                  
       end.tv_sec -= nsec;                                     
     }                                           

     result->tv_sec = end.tv_sec - start.tv_sec;                                 
     result->tv_usec = end.tv_usec - start.tv_usec;                                

     return end.tv_sec < start.tv_sec;                                   
}                                             

void set_exec_time(int end)                                       
{                                             
     static struct timeval time_start;                                   
     struct timeval time_end;                                      
     struct timeval time_diff;                                     

     if (end) {                                         
       gettimeofday(&time_end, NULL);                                  
       if (timeval_subtract(&time_diff, time_end, time_start) == 0) {                          
         if (end == 1)                                    
           printf("\nexec time: %1.2fs\n",                              
             time_diff.tv_sec + (time_diff.tv_usec/1000000.0f));                      
         else if (end == 2)                                   
           printf("%1.2fs",                                  
             time_diff.tv_sec + (time_diff.tv_usec/1000000.0f));                      
       }                                         
       return;                                        
     }                                           
     gettimeofday(&time_start, NULL);                                    
}                                             

void start_exec_timer()                                        
{                                             
     set_exec_time(0);                                       
}                                             

void print_exec_timer()                                        
{                                             
     set_exec_time(1);                                       
} 
Cuestiones relacionadas