2011-12-21 11 views
7

Sto cercando di calcolare il numero di zecche una funzione utilizza per correre e per fare in modo che un usando la funzione clock() in questo modo:orologio() di precisione in time.h

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

Ma il problema è che la valore restituito è un multiplo di 10000, che penso sia lo CLOCK_PER_SECOND. Esiste un modo o un valore di funzione equivalente che sia più preciso?

Sto usando Ubuntu 64-bit, ma preferirei che la soluzione possa funzionare su altri sistemi come Windows & Mac OS.

+2

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

+0

Non è una buona idea denominare una variabile 'time', specialmente se si sta usando' ', poiché esiste una funzione standard con quel nome. –

+0

ho usato il tempo come nome della variabile solo per lo scopo della domanda. – mteffaha

risposta

7

Ci sono un numero di timer più accurati in POSIX.

  • gettimeofday() - ufficialmente obsolescente, ma molto ampiamente disponibile; risoluzione microsecondo.
  • clock_gettime() - la sostituzione per gettimeofday() (ma non necessariamente così ampiamente disponibile, su una vecchia versione di Solaris, richiede -lposix4 da collegare), con risoluzione di nanosecondi.

Ci sono altri sub-secondo timer di maggiore o minore antichità, la portabilità, e la risoluzione, tra cui:

  • ftime() - risoluzione millisecondi (indicata 'legacy' in POSIX 2004; non in POSIX 2008) .
  • clock() - di cui già conosci. Si noti che misura il tempo della CPU, non il tempo trascorso (orologio da parete).
  • times() - CLK_TCK o HZ. Si noti che questo misura il tempo della CPU per i processi padre e figlio.

Non utilizzare ftime() o times() a meno che non ci sia niente di meglio. Il fallback finale, ma non soddisfare le vostre esigenze immediate, è

  • time() - uno secondo risoluzione.

I clock() relazioni funzionali in unità di CLOCKS_PER_SEC, che è richiesto per essere 1,000,000 da POSIX, ma l'incremento può verificarsi meno frequentemente (100 volte al secondo era una frequenza comune). Il valore restituito deve essere definito da CLOCKS_PER_SEC per ottenere il tempo in secondi.

+2

Beh, il fatto che sia disponibile su Solaris è una buona cosa. Un altro sistema operativo che punta alla conformità POSIX. Detto questo, tuttavia, POSIX non richiede che il simbolo sia disponibile con almeno '-lrt'? –

+0

Ho scritto quelle note qualche tempo fa - forse l'era di Solaris 2.6 (hmmm ... 1998 ... sì, un po 'di tempo fa!). Quindi la libreria richiesta potrebbe essere cambiata. –

+0

@ jørgensen: il collegamento è POSIX 2008 ed è ancora elencato come parte di POSIX, anche se contrassegnato come obsoleto dal numero 7 (che è il [POSIX 2008] (http://pubs.opengroup.org/onlinepubs/9699919799/toc .htm) standard, vedere l'intestazione delle pagine collegate a). Quindi, credo che tu sia prematuro nel dichiarare obsoleto 'gettimeofday()'; è ancora obsoleto. –

1

Per la pagina di manuale clock(), su piattaforme POSIX il valore della macro CLOCKS_PER_SEC deve essere 1000000. Come dici tu il valore di ritorno che stai ricevendo da clock() è un multiplo di 10000, ciò implicherebbe che il valore restituito la risoluzione è 10 ms.

Si noti inoltre che clock() su Linux restituisce un'approssimazione del tempo del processore utilizzato dal programma. Su Linux, ancora una volta, le statistiche degli scheduler vengono aggiornate quando viene eseguito lo scheduler, alla frequenza CONFIG_HZ. Quindi, se il tick del timer periodico è 100 Hz, si ottengono le statistiche sul consumo di tempo della CPU del processo con una risoluzione di 10 ms.

Le misurazioni di Walltime non sono vincolate da questo e possono essere molto più accurate. clock_gettime (CLOCK_MONOTONIC, ...) su un moderno sistema Linux fornisce una risoluzione di nanosecondi.

+0

ringrazia ogni corpo per le risposte, sono stato in grado di farlo con clock_gettime. – mteffaha

1

Il modo più preciso (ma estremamente portatile) per misurare il tempo è contare i tick della CPU.

Per esempio su 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(); 

Se non si dispone di un sistema x86, dovrete ri-scrivere il codice assembler di conseguenza per la CPU. Se il tuo numero di telefono ha bisogno della massima precisione, è spiacevole che l'unico modo per andare ... altrimenti usi clock_gettime().

-1

Sono d'accordo con la soluzione di Jonathan. Ecco l'implementazione di clock_gettime() con nanosecondi di precisione.

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

    } 
} 

Anche se è difficile da raggiungere ns precisione, ma questo può essere usato per ottenere precisione per meno di un microsecondi (700-900 ns). printf above è usato per stampare solo il thread # (ci vorranno sicuramente 2-3 micro secondi per stampare una dichiarazione).