¿El mejor método de tiempo en C?

5 minutos de lectura

avatar de usuario
lilq

¿Cuál es la mejor manera de cronometrar una sección de código con alta resolución y portabilidad?

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

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

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

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

  • Esto es realmente bueno ya que le da tiempo de CPU en lugar de tiempo transcurrido (el tiempo transcurrido podría verse afectado 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.

    – pax diablo

    20 de enero de 2009 a las 1:22

  • Usé esto cientos de veces y es la solución mejor/más fácil para esta pregunta

    – Gerardo

    21 de enero de 2009 a las 6:18

  • incluso puedes meter todo esto en una macro si estás cronometrando varias cosas con frecuencia: #define timing(a) start=clock(); a; diff = reloj() – inicio; mseg = diferencia * 1000 / RELOJES_POR_SEG; printf(“msegs: %d\n”,mseg); y luego invoque: timing(IntenseFunc1())

    – eqzx

    26 de febrero de 2012 a las 19:03


  • clock_t suele ser largo y CLOCKS_PER_SEC es 1000000. En este caso, una diferencia de más de 4 segundos le dará un desbordamiento y resultados extraños.

    – Begelfor

    5 de marzo de 2014 a las 13:22

  • @paxdiablo Obtengo resultados completamente equivalentes con esto que con gettimeofday(), no estoy seguro de lo que estás diciendo aquí.

    – usuario3467349

    21/10/2014 a las 21:47


gettimeofday() probablemente hará lo que quieras.

Si utiliza hardware Intel, así es como se lee el contador de instrucciones en tiempo real de la CPU. Le dirá la cantidad de ciclos de CPU ejecutados desde que se inició el procesador. Este es probablemente el contador de gastos generales más fino y más bajo que puede obtener para la medición del rendimiento.

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

Cuando ejecuto esto en mi caja, obtengo

11867927879484732
11867927879692217
it took this long to call printf: 207485

Aquí esta la Guía del desarrollador de Intel que da toneladas de detalle.

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

obtener la hora del día devolverá la hora con una precisión de microsegundos dentro de la resolución del reloj del sistema. También es posible que desee consultar el Temporizadores de alta resolución proyecto en SourceForge.

yo suelo SDL_GetTicks desde el biblioteca SDL.

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

Utilizo lo 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);                                                                                                                                                           
}

La alta resolución es relativa… Estaba mirando los ejemplos y en su mayoría se adaptan a milisegundos. Sin embargo, para mí es importante medir microsegundos. No he visto una solución independiente de la plataforma para microsegundos y pensé que algo como el siguiente código sería útil. Estaba cronometrando en Windows solo por el momento y lo más probable es que agregue una implementación de gettimeofday() cuando haga 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

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad