Newsgroup: it.comp.lang.c
Titolo: calcolare il tempo

Salve a tutti,
per calcolare il tempo trascorso per eseguire un gruppo di istruzioni ho 
provato a fare cosi':
/*****************/
time_t inizio, fine;
double tempo;
inizio = time(NULL);
... istruzioni varie ...
fine = time(NULL);
tempo = difftime(fine,inizio);
/******************/
la risoluzione pero' e' del secondo. Volendola aumentare ho usato clock().
/*****************/
clock_t inizio, fine;
long tempo;
inizio = clock();
... istruzioni varie ...
fine = clock();
tempo = (fine-inizio)/CLOCKS_PER_SEC;
/******************/
Questo sembra funzionare.
Se, pero', al posto di "istruzioni varie", c'e' qualcosa del tipo
fgets(str,128,stdin);
il tempo calcolato con clock() e' 0.
Qualche spiegazione?
Grazie
Fabio

 il tempo calcolato con clock() e' 0.
Le spiegazioni sono nel manuale on-line dove
viene spiegato cosa fa clock()....
Comunque, riassumendo, clock() non
misura il tempo trascorso, ma misura "approssimativamente",
il tempo di CPU usato.
Inoltre non ha una risoluzione uguale alla frequenza di clock,
ma spesso una risoluzione attorno al centesimo di secondo,,
quindi una sequenza di istruzioni molto veloci puo' darti comunque 0.
ciao,
g.

 quindi una sequenza di istruzioni molto veloci puo' darti comunque 0.
ok, ma se voglio misurare il tempo di battitura di una frase? non si 
tratta di istruzioni veloci. Credo che il problema stia nel tempo di CPU 
che risulta nullo quando il sistema aspetta l'input.
In definitiva come fare a calcolare questo tempo con risoluzione 
inferiore al secondo?
grazie

 Qualche spiegazione?
leggi sopra ;)
ciao.

 float o double :)
hai ragione, ma il codice vero era:
long tempo;
...
tempo = fine-inizio; /* e questo e' giusto */
double t = (double)tempo/CLOCKS_PER_SEC;

Io adotto questa soluzione,
__asm__ volatile (".byte 0x0f, 0x31"
: "=A" (tv_start));
err = ip_route_output(&rt, daddr, rfh.saddr,
tos, ipc.oif);
__asm__ volatile (".byte 0x0f, 0x31"
:"=A" (tv_end));
ciao
per i dettagli 
www.it-sec.it

Forse prima sono stato un pò troppo sintetico:
La misura deve essere effettuata con una architettura intel, infatti
dal modello Pentium in poi, è possibile utilizzare una particolare
caratteristica dei suoi Microprocessori. Ogni microprocessore Intel è
dotato di un " Time Stamp Counter " (TSC), un particolare registro a 64
bit. Questo registro può essere letto con la funzione assembler
rdtsc().
extern __inline__ unsigned long long int rdtsc()
{
unsigned long long int x; __asm__ volatile
(".byte 0x0f, 0x31" : "=A" (x));
return x;
}
TSC  vale 0 al momento dell'accensione viene incrementato ad ogni
segnale del clock. Questo significa, nel caso di un processore a 700MH
viene incrementato ogni 1.42 nanosecondi.
Per la misura devi inserire  una coppia di istruzioni assembler del
tipo unsigned long long int x; __asm__ volatile (".byte 0x0f, 0x31" :
"=A" (x));
 chiamata che restituisce i cicli di clock trascorsi dal momento
dell'accensione. Il codice completo è il seguente:
__asm__ volatile (".byte 0x0f, 0x31"
: "=A" (tv_start));
err = Funzione_da_misurare(&rt, daddr, rfh.saddr, tos, ipc.oif);
__asm__ volatile (".byte 0x0f, 0x31"
:"=A" (tv_end));
La differenza tra le variabili tv_end e tv_start indica il cicli di
clock trascorsi esattamente per l'esecuzione della funzione
Funzione_da_misurare() . 
ciao 
www.it-sec.it

ti ringrazio delle spiegazioni, cercavo qualcosa di piu' portatile, ma 
non credo ci sia qualcosa.
tra l'altro non ho neanche un Intel :-)
ciao

 double t = (double)tempo/CLOCKS_PER_SEC;
O_o scusa, com'è che t è long e poi per magia diventa 
double? non mi pare una sintassi corretta.
cmq, io non ho riscontrato i problemi di cui parlavi. prova 
questo esempio, il tempo viene visualizzato correttamente:
#include <stdio.h>
#include <time.h>
int main() {
    clock_t inizio, fine;
    float tempo;
    char str[256];
    inizio = clock();
    fgets(str,128,stdin);
    fine = clock();
    tempo = ((float)(fine-inizio))/CLOCKS_PER_SEC;
    printf("%f",tempo);
    return 0;
}
ciao.

 pare una sintassi corretta.
premetto che non ho ancora provato il tuo esempio.
Cmq, "tempo" e' di tipo long perche' conta quanti clock (numero intero) 
passano tra inizio e fine.
Poi devo dividere "tempo" per la costante "CLOCKS_PER_SEC" e il 
risultato deve essere un double, quindi "t" e' double e l'operazione 
viene eseguita con un cast.
ciao

 viene eseguita con un cast.
si scusami, il cast va bene, ma avevo letto di fretta e non 
so come il mio cervello bacato aveva reinterpretato t come 
tempo :D
ciao.

 ciao.
spiacente, ma restituisce cmq 0.00000
ciao

 spiacente, ma restituisce cmq 0.00000
O_o wow... giusto per info: che compilatore usi?
ciao.

 ciao.
gcc sotto linux


mm... sotto win non mi da problemi, ma in effetti sotto 
linux il risultato è 0. e sia "inizio" che "fine" sono a 0...
però dalla man page leggo:
On several other implementations, the value returned  by 
clock()  also includes  the times of any children whose 
status has been collected via wait() (or another wait-type 
call).  Linux does not include  the  times of  waited-for 
children in the value returned by clock().  The times() 
function, which explicitly returns  (separate)  information 
  about  the caller and its children, may be preferable.
può darsi che sia questo il caso?
ciao.

cane ha scritto:

si, puo' darsi. peccato che times() come ho gia' scritto abbia la 
risoluzione del secondo
ciao e grazie

 risoluzione del secondo
la funzione indicata è times(), mi pare che tu abbia 
riportato di aver usato time().
cmq, ho fatto dei test anche con times() e non ci ho cavato 
nulla.
invece ho ottenuto qualcosa con gettimeofday() che riporta 
anche il tempo in microsecondi.
prova questo esempio:
----------------------------------------
#include <stdio.h>
#include <time.h>
#include <sys/time.h>
int main() {
    struct timeval inizio, fine;
    double tempo;
    char s[256];
    gettimeofday(&inizio,NULL);
    fgets(s,128,stdin);
    gettimeofday(&fine,NULL);
    if(fine.tv_usec<inizio.tv_usec)
 
tempo=(fine.tv_sec-inizio.tv_sec)+(double)(1000000-fine.tv_usec+inizio.tv_usec)/1000000;
    else
 
tempo=(fine.tv_sec-inizio.tv_sec)+(double)(fine.tv_usec-inizio.tv_usec)/1000000;
    printf("%f\n",tempo);
    return 0;
}
----------------------------------------
ammetto che è un "workaround" un po' brutale... e non ho 
ancora capito lo strano comportamento di clock().
ciao.

profil(3) - Linux man page
NAME
profil - execution time profile
SYNOPSIS
#include <unistd.h>
int profil(u_short *buf, size_t bufsiz, size_t offset, u_int scale);
DESCRIPTION
This routine provides a means to find out in what areas your program
spends most of its time. The argument buf points to bufsiz bytes of
core. Every virtual 10 milliseconds, the user's program counter (PC) is
examined: offset is subtracted and the result is multiplied by scale
and divided by 65536. If the resulting value is less than bufsiz, then
the corresponding entry in buf is incremented. If buf is NULL,
profiling is disabled.
RETURN VALUE
Zero is always returned.
BUGS
profil cannot be used on a program that also uses ITIMER_PROF itimers.
True kernel profiling provides more accurate results. Libc 4.4
contained a kernel patch providing a system call profil.
CONFORMING TO
Similar to a call in SVr4 (but not POSIX.1).
SEE ALSO 
gprof(1), setitimer(2), signal(2), sigaction(2)

 ciao.
ho letto nel file sys/time.h che la struttura timeval e' obsoleta.
Nel file time.h e' invece presente la struttura timespec che dovrebbe 
fare lo stesso lavoro, ma usando i nanosecondi.
La funzione che assegna valore alla struttura timespec e' 
clock_gettime(), ma non sono riuscito ad usarla perche' ci sono problemi 
in fase di link.
Giusto per capirci lo stesso errore che si ottiene se si compila un 
programma in cui e' presente una funzione matematica e non si specifica 
-lm a riga di comando.
Quale libreria devo aggiungere?
ciao

 Quale libreria devo aggiungere?
la funzione mi è ignota, non so cosa suggerirti :(
ciao.

 la funzione mi è ignota, non so cosa suggerirti :(
ok, grazie di tutto
ciao