2011-12-21 14 views
7

Estoy tratando de calcular el número de garrapatas una función utiliza para correr y hacerlo utilizando la función de un clock() así:reloj() precisión en time.h

unsigned long time = clock(); 
myfunction(); 
unsigned long time2 = clock() - time; 
printf("time elapsed : %lu",time2); 

pero el problema es que la el valor que devuelve es un múltiplo de 10000, que creo que es el CLOCK_PER_SECOND. ¿Hay una forma o un valor de función equivalente que sea más preciso?

Estoy usando Ubuntu 64-bit, pero preferiría que la solución funcione en otros sistemas como Windows & Mac OS.

+2

ver http://stackoverflow.com/questions/538609/high-resolution-timer-with-c-and-linux – NPE

+0

No es una buena idea nombrar una variable 'time', especialmente si está usando' ', ya que hay una función estándar con ese nombre. –

+0

utilicé el tiempo como nombre de variable solo para el propósito de la pregunta. – mteffaha

Respuesta

7

Existen varios temporizadores más precisos en POSIX.

  • gettimeofday() - oficialmente obsoleto, pero muy ampliamente disponible; resolución microsegunda
  • clock_gettime() - el reemplazo de gettimeofday() (pero no necesariamente tan ampliamente disponible; en una versión anterior de Solaris, requiere -lposix4 para vincular), con una resolución de nanosegundos.

Hay otros temporizadores menos de un segundo de mayor o menor antigüedad, portabilidad y resolución, entre ellos:

  • ftime() - resolución de milisegundos (marcado 'legado' en POSIX 2004; No en POSIX 2008) .
  • clock() - que ya conoce. Tenga en cuenta que mide el tiempo de CPU, no el tiempo transcurrido (reloj de pared).
  • times() - CLK_TCK o HZ. Tenga en cuenta que esto mide el tiempo de CPU para los procesos padre e hijo.

No utilice ftime() o times() a menos que no haya nada mejor. La última alternativa, pero no cumple con sus requisitos inmediatos, es

  • time() - una segunda resolución.

Los clock() informes la función en unidades de CLOCKS_PER_SEC, que se requiere para ser 1,000,000 por POSIX, pero el incremento puede ocurrir con menos frecuencia (100 veces por segundo fue una frecuencia común). El valor de retorno debe estar definido por CLOCKS_PER_SEC para obtener el tiempo en segundos.

+2

Bueno, el hecho de que esté disponible en Solaris es algo bueno. Un SO más esforzándose por cumplir con POSIX. Dicho esto, sin embargo, ¿POSIX no exige que el símbolo esté disponible con al menos '-lrt'? –

+0

Escribí esas notas hace un tiempo, tal vez era Solaris 2.6 (hmmm ... 1998 ... sí, ¡hace bastante tiempo!). Entonces la biblioteca requerida puede haber cambiado. –

+0

@ jørgensen: El enlace es para POSIX 2008 y todavía aparece como parte de POSIX, aunque marcado como obsoleto desde el Número 7 (que es [POSIX 2008] (http://pubs.opengroup.org/onlinepubs/9699919799/toc) .htm) estándar; vea el encabezado de las páginas vinculadas a). Por lo tanto, creo que eres prematuro al declarar 'gettimeofday()' obsoleto; es simplemente obsoleto todavía. –

1

Por la página de manual clock(), en plataformas POSIX el valor de la macro CLOCKS_PER_SEC debe ser 1000000. Como dices que el valor de retorno que obtienes de clock() es un múltiplo de 10000, eso implicaría que la resolución es 10 ms.

También tenga en cuenta que clock() en Linux devuelve una aproximación del tiempo de procesador utilizado por el programa. En Linux, nuevamente, las estadísticas del planificador se actualizan cuando se ejecuta el planificador, a la frecuencia CONFIG_HZ. Entonces, si la marca del temporizador periódico es de 100 Hz, obtendrá estadísticas de consumo de tiempo de CPU de proceso con una resolución de 10 ms.

Las mediciones de Walltime no están vinculadas por esto, y pueden ser mucho más precisas. clock_gettime (CLOCK_MONOTONIC, ...) en un sistema Linux moderno proporciona una resolución de nanosegundos.

+0

agradece a cada cuerpo por sus respuestas, Pude hacer con clock_gettime. – mteffaha

1

La forma más precisa (pero muy no portátil) de medir el tiempo es contar los tics de la CPU.

Por ejemplo en x86

unsigned long long int asmx86Time() 
{ 
    unsigned long long int realTimeClock = 0; 
    asm volatile ("rdtsc\n\t"   
        "salq $32, %%rdx\n\t"  
        "orq %%rdx, %%rax\n\t" 
        "movq %%rax, %0"   
        : "=r" (realTimeClock) 
        : /* no inputs */ 
        : "%rax", "%rdx"); 
    return realTimeClock; 
} 

double cpuFreq() 
{ 
    ifstream file ("/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq"); 
    string sFreq; if (file) file >> sFreq; 
    stringstream ssFreq (sFreq); double freq = 0.; 
    if (ssFreq) { ssFreq >> freq; freq *= 1000; } // kHz to Hz 
    return freq; 
} 

// Timing 

unsigned long long int asmStart = asmx86Time(); 
doStuff(); 
unsigned long long int asmStop = asmx86Time(); 
float asmDuration = (asmStop - asmStart)/cpuFreq(); 

Si usted no tiene un sistema x86, que tendrá que volver a escribir el código ensamblador en consecuencia para su CPU. Si necesita precisión máxima, desafortunadamente es la única manera de hacerlo ... de lo contrario, use clock_gettime().

-1

Estoy de acuerdo con la solución de Jonathan. Aquí está la implementación de clock_gettime() con nanosegundos de precisión.

//Import 
#define _XOPEN_SOURCE 500 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <time.h> 
#include <sys/time.h> 


int main(int argc, char *argv[]) 
{ 
    struct timespec ts; 
    int ret; 
    while(1) 
    { 
     ret = clock_gettime (CLOCK_MONOTONIC, &ts); 
     if (ret) 
     { 
      perror ("clock_gettime"); 
      return; 
     } 
     ts.tv_nsec += 20000; //goto sleep for 20000 n 
     printf("Print before sleep tid%ld %ld\n",ts.tv_sec,ts.tv_nsec); 
     // printf("going to sleep tid%d\n",turn); 
     ret = clock_nanosleep (CLOCK_MONOTONIC, TIMER_ABSTIME,&ts, NULL); 

    } 
} 

Aunque es difícil de lograr ns precisión, pero esto puede ser utilizado para obtener una precisión de menos de unos microsegundos (700-900 ns). printf arriba se usa para imprimir el número de hilo (definitivamente tardará 2-3 microsegundos en imprimir una declaración).