2012-03-26 21 views
8

Ho qualcosa di simile:perché orologio C() restituisce 0

clock_t start, end; 
start=clock(); 

something_else(); 

end=clock(); 
printf("\nClock cycles are: %d - %d\n",start,end); 

e ottengo sempre come uscita "cicli di clock sono: 0-0"

Qualsiasi idea del perché questo accade ?

(Giusto per dare pochi dettagli, la funzione something_else() esegue un esponenziazione da sinistra a destra usando la rappresentazione montgomery, inoltre non so per certo che la funzione something_else() abbia effettivamente un tempo non trascurabile.)

Questo è su Linux. Il risultato di uname -a è:

Linux snowy.*****.ac.uk 2.6.32-71.el6.x86_64 #1 SMP Fri May 20 03:51:51 BST 2011 x86_64 x86_64 x86_64 GNU/Linux

+2

Quale sistema operativo stai usando? – trojanfoe

+0

Ho appena modificato la domanda per aggiungere questo dettaglio! –

+1

'clock_t' probabilmente non è un' int', quindi '% d' non è appropriato. Vedi questa domanda: http://stackoverflow.com/questions/1083142/whats-the-correct-way-to-use-printf-to-print-a-clock-t. –

risposta

6

clock la funzione non misura i cicli di clock della CPU.

C dice clock"restituisce migliore approssimazione della realizzazione al tempo del processore utilizzato dal programma dall'inizio di un'era definito dall'implementazione legati solo per l'invocazione del programma."

Se tra due successive clock chiamate programma richiede meno tempo di un'unità della funzione di clock, si potrebbe ottenere 0.

POSIX clock definisce l'unità con CLOCKS_PER_SEC come 1000000 (l'unità è quindi 1 microsecondo).

http://pubs.opengroup.org/onlinepubs/009604499/functions/clock.html

Per misurare cicli di clock a x86/x64 è possibile utilizzare assembly inline per prelevare il conteggio orologio del tempo di CPU Stamp Counter registrare rdtsc.

+1

Quello che dici del contatore dei timestamp suona davvero interessante. Puoi indicare una buona fonte su cui leggere? Grazie mille –

+0

Inoltre, è utile notare che mentre clock() è una funzione nello standard C90, ci sono piattaforme in cui clock() è tecnicamente non supportato e viene implementato per restituire sempre -1. – rrrzx

4

Beh, vuoi il tempo something_else() prende? Prova questo:

#include <sys/time.h> 
#include <stdio.h> 
#include <unistd.h> 
int main(void) { 
struct timeval start, end; 
long mtime, secs, usecs;  

gettimeofday(&start, NULL); 
something_else(); 
gettimeofday(&end, NULL); 
secs = end.tv_sec - start.tv_sec; 
usecs = end.tv_usec - start.tv_usec; 
mtime = ((secs) * 1000 + usecs/1000.0) + 0.5; 
printf("Elapsed time: %ld millisecs\n", mtime); 
return 0; 

}

+0

Sfortunatamente ho bisogno di cicli di clock, non del tempo. –

+1

Non penso che sarete in grado di misurare in modo portabile i cicli di clock. Non penso ci sia nulla a riguardo nello standard C o POSIX. – Guido

+0

@eddy ed, se si desidera misurare i cicli di clock, è necessario utilizzare un analizzatore logico, un contatore di frequenza o altro strumento di misurazione hardware collegato all'hardware. – mah

2

controllare il valore di CLOCKS_PER_SEC in time.h/clock.h. Nel mio sistema, ad esempio, (Dev Cpp su Windows 7) è solo un 1000. Quindi, per quanto riguarda il mio programma, ci sono 1000 tick al secondo. Il tuo something_else verrebbe eseguito in pochi microsecondi. E quindi clock() restituisce zero sia prima che dopo la chiamata di funzione.

Sul mio sistema, quando ho sostituire la something_else con un tempo di routine come questo

for (unsigned i=0xFFFFFFFF;i--;); 

start=clock(); 

for (unsigned i=0xFFFFFFFF;i--;); 

end=clock(); 

ottengo

cicli di clock sono: 10236 - 20593

Da un di linux box, trovo quanto segue in bits/time.h

/* ISO/IEC 9899:1990 7.12.1: <time.h> 
    The macro `CLOCKS_PER_SEC' is the number per second of the value 
    returned by the `clock' function. */ 
/* CAE XSH, Issue 4, Version 2: <time.h> 
    The value of CLOCKS_PER_SEC is required to be 1 million on all 
    XSI-conformant systems. */ 
# define CLOCKS_PER_SEC 1000000l 

in modo da considerare questo prima di analizzare il valore di ritorno di clock()

2

Il modo giusto di usare l'orologio() per misurare il tempo potrebbe essere:

printf("\nTime elapsed: %.2f\n",1.0*(end-start)/CLOCKS_PER_SEC); 

Questo perché clock_t non è garantito per essere un int, o qualsiasi altro tipo per quella materia.

+0

L'OP è interessato a sapere perché 'start' e' end' stanno diventando 0? In tal caso, il virgola mobile non aiuta –

+0

Ciò che intendo è che potrebbero non essere di tipo int, quindi la stampa non ha senso. Il modo corretto per usarli è sottrarre due degli importi e dividendo per CLOCKS_PER_SEC. Praticamente qualsiasi altra cosa non è definita. Il codice che ho dato funziona correttamente mostrando la quantità di secondi trascorsi. – Guido

5

Credo che il motivo è che il vostro something_else() consuma così poco tempo che superano la precisione di clock(). Ho provato a chiamare clock() due volte di conseguenza e sia start e end è zero, ma il risultato è ragionevole quando faccio un po 'di cose che richiede tempo tra.

Ecco il mio codice di prova frammento di:

int main(void) { 
    clock_t start, end; 
    start = clock(); 
    int c; 
    for (int i = 0; i < 100; i++) { 
     for (int j = 0; j < (1<<30); j++) { 
      c++; 
     } 
    } 
    printf("start = %d, end = %d\n", start, end); 
    return 0; 
} 

E il risultato sul mio computer è:

start = 0, end = 27700000 

Inoltre, due punte:

  1. Quando il test, no utilizzare qualsiasi ottimizzazione del compilatore. Potresti pensare che il tuo something_else() richieda parecchio tempo, ma il compilatore può semplicemente ignorare quelle operazioni (in particolare i cicli) poiché le ritengono prive di significato.
  2. Utilizzare sizeof(clock_t) sulla piattaforma per visualizzare le dimensioni di clock_t.
+0

Ho provato il tuo codice sul mio sistema. Ci vogliono diversi secondi per correre, ma ho ancora due Zero. Ho anche provato a stamparlo come printf ("\ nTempo trascorso:% .2f \ n", 1.0 * (fine-inizio)/CLOCKS_PER_SEC); ma ottengo ancora zero. C'è sicuramente qualcosa di sbagliato nella funzione orologio. C'è qualche bandiera che ho bisogno di impostare o qualcosa che qualcuno di voi è a conoscenza? –

+0

@eddyed: 'start' dovrebbe essere zero poiché registra il tempo trascorso dall'avvio del programma, ma' end' NON dovrebbe essere zero. Per quanto ne so, non sono necessarie bandiere speciali o altri trucchi per usare 'clock()'. A proposito, qual è il risultato di 'sizeof (clock_t)' sulla tua piattaforma? –

+0

+1 per * non ottimizza * –

0

Ho usato il piccolo programma qui sotto per studiare l'ora dell'orologio a muro e il tempo della CPU.

Sul mio sytem prova Questo stampa

CLOCKS_PER_SEC 1000000

CPU time usage resolutio n sembra essere 0.010000 seconds

gettimeofday cambiata 9634 uS quando il tempo di CPU modificata 0.010000

risoluzione gettimeofday sembra essere uno di noi

#include <stdio.h> 
#include <unistd.h> 
#include <sys/time.h> 
#include <ctime> 


int main(int argc, char** argv) { 

    struct timeval now; // wall clock times 
    struct timeval later; 

    clock_t tNow = clock(); // clock measures CPU time of this Linux thread 
    gettimeofday(&now, NULL); // wall clock time when CPU time first read 

    clock_t tLater = tNow; 
    while (tNow == tLater) 
      tLater = clock(); // consume CPU time 

    gettimeofday(&later, NULL); // wall clock time when CPU time has ticked 

    printf("CLOCKS_PER_SEC %ld\n",CLOCKS_PER_SEC); 

    double cpuRes = (double)(tLater - tNow)/CLOCKS_PER_SEC; 

    printf("CPU time usage resolution looks to be %f seconds\n", cpuRes); 

    unsigned long long nowUs = ((unsigned long long)now.tv_sec) * 1000000ULL; 
    nowUs += (unsigned long long)now.tv_usec; 

    unsigned long long laterUs = ((unsigned long long)later.tv_sec) * 1000000ULL; 
    laterUs += (unsigned long long)later.tv_usec; 

    printf("gettimeofday changed by %d uS when CPU time changed by %f seconds\n", (int)(laterUs - nowUs), cpuRes); 

    // now measure resolution of gettimeofday 

    gettimeofday(&now, NULL); 
    later = now; 

    while ((now.tv_sec == later.tv_sec) && (now.tv_usec == later.tv_usec)) 
      gettimeofday(&later, NULL); 

    nowUs = ((unsigned long long)now.tv_sec) * 1000000ULL; 
    nowUs += (unsigned long long)now.tv_usec; 

    laterUs = ((unsigned long long)later.tv_sec) * 1000000ULL; 
    laterUs += (unsigned long long)later.tv_usec; 

    printf("gettimeofday resolution looks to be %d us\n", (int)(laterUs - nowUs)); 

}