PDA

View Full Version : [C] Cronometrare tempo di esecuzione di un programma


Doriän
27-06-2007, 17:46
Esiste un modo di implementare nel codice di un programma un algoritmo/po' di codice che calcoli il tempo di esecuzione dello stesso? Il bisogno nasce dalla mia scimmia nascente per http://projecteuler.net, e dalla necessità (mista anche a curiosità e desiderio di ottimizzazione di codice asd) di sapere quanto tempo impiega il programma che sviluppo per risolvere il quesito a svolgere il suo compito. Idee?
Mi era parso di scorgere una cosa del genere fatta con Python (occhio, spoiler di uno dei problemi del sito (http://cow.neondragon.net/index.php/1765-Finding-Primes)), però anche frugando in giro non ho trovato molto per il C...

cionci
27-06-2007, 22:43
Sistema operativo ? Risoluzione della misura (secondi, millisecondi, nanosecondi :eek: ) ?

Doriän
27-06-2007, 23:44
Win Xp, e penso che vadano di lusso i decimi di secondo ^^!
Dal blog che ho linkato,
Stop at square root method
The 1001st prime number is 7927
Time Taken: 0:00:00.313000

senza andare troppo in la, quindi fermandosi alla prima o anche seconda cifra dopo i secondi, va più che bene, imho. Oh poi non so, sono aperto a tutti i consigli eh!

cionci
28-06-2007, 00:34
Allora ti servono le api di Windows. Il C standard può andare solo fino ai secondi.

http://msdn2.microsoft.com/en-us/library/ms713418.aspx

Devi includere windows.h e linkare winmm.lib o libwinmm.a (se hai un compilatore derivato da gcc)...

Basta fare una chiamata all'inizio ed una alla fine dell'intervallo che vuoi misurare.
Memorizzi il valore ritornato in un unsigned int e poi fai la differenza fra i due valori (fine - inizio) per ottenere i millisecondi trascorsi.

Doriän
28-06-2007, 10:48
MMh ok, gracias! Provo un po' e al limite ti faccio sapere! Grazie ancora!

tomminno
28-06-2007, 12:17
Per Win32 e misurazioni di precisione c'è QueryPerformanceCounter, citato anche nell'MSDN riportata da cionci

Doriän
28-06-2007, 12:30
Mmh, non gli piace. Ho implementato tutto bene, fatte le due chiamate, una all'ìinizio e una proprio prima di finire, storate su due diverse variabili che poi vado a sottrarre alla fine. Incuriosito dal fatto che mi desse 0, sono andato a vedere il valore delle variabili. Entrambe danno esattamente 4199472 come valore; ho pensato che fosse a causa del tipo di variabile (unsigned int), ho provato a cambiare in long ma niente, stesso valore. L'unica cosa è che il Dev mi da un warning in fase di compilazione, "assignment makes integer from pointer without a cast". Bho!

andbin
28-06-2007, 12:37
Posta il sorgente (magari non tutto se è lungo, solo le parti dove dichiari le variabili e dove fai le chiamate per ottenere il tempo e poi i calcoli).

Doriän
28-06-2007, 12:43
#include<stdio.h>
#include<math.h>
#include<windows.h>

int isPrime(long int a);

int main(int argc[], char *argv[])
{
long int i, x, primes[10001];
unsigned int time_start, time_end, time;

time_start = timeGetTime;

...
blablabla
...

time_end = timeGetTime;

time = time_end - time_start;

printf("\nStart time: %u.\nEnd time: %u.\nTime Elapsed: %u.\n\n", time_start, time_end, time);
printf("The 10001st prime number is %ld.\n", primes[x-1]);

printf("Press any key to continue.\n");
getch();

return(0);
}

int isPrime(long int a)
{
blablabla
}

andbin
28-06-2007, 12:52
unsigned int time_start, time_end, time;

time_start = timeGetTime;timeGetTime è una funzione, non una variabile. E ritorna un DWORD.

DWORD timeGetTime(VOID);

Quindi:
DWORD time_start, time_end, time;

time_start = timeGetTime ();

ecc...

cionci
28-06-2007, 12:56
timeGetTime(), mancano le parentesi...mettendo solo il nome della funzione in pratica ne usi il puntatore...

Doriän
28-06-2007, 12:59
http://gaming.ngi.it/forum/images/ngismiles/insane.gif funziona! http://gaming.ngi.it/forum/images/ngismiles/insane.gif grazie! http://gaming.ngi.it/forum/images/ngismiles/insane.gif

cionci
28-06-2007, 12:59
Vabbè...di fatto un DWORD è un unsigned int....

andbin
28-06-2007, 13:18
Vabbè...di fatto un DWORD è un unsigned int....A dire il vero è un unsigned long. Cambia nulla come dimensione, lo so .... ma se su MSDN leggo DWORD, io personalmente metto DWORD. Vuoi perché sono fatto così ... vuoi per pura coerenza.

cionci
28-06-2007, 13:30
Per carità anche io quando programmo in Win32...ma non gli volevo mettere troppo carne al fuoco ;)

gepeppe
30-09-2007, 16:27
ma se uno volesse fare lo stesso senza usare le api di windows?? stò su linux, quindi non posso usarle :D

cionci
30-09-2007, 16:30
No se vuoi una risoluzione più bassa del secondo.

gepeppe
30-09-2007, 16:47
mi vanno bene anche i secondi...come si fa?

cionci
30-09-2007, 16:53
time_t start = time(NULL);
....
time_t end = time(NULL);

printf("Tempo trascorso: %d", end - start);

gepeppe
30-09-2007, 16:57
funziona..ti ringrazio :)

variabilepippo
30-09-2007, 17:00
Per migliorare la risoluzione in ambiente Linux puoi usare la funzione gettimeofday (http://www.penguin-soft.com/penguin/man/2/gettimeofday.html?manpath=/man/man2/gettimeofday.2.inc):


static struct timeval _tstart, _tend;

static struct timezone tz;

void tstart(void)

{

gettimeofday(&_tstart, &tz);

}

void tend(void)

{

gettimeofday(&_tend,&tz);

}


double elapsedtime()

{

double t1, t2;

t1 = (double)_tstart.tv_sec + (double)_tstart.tv_usec/(1000*1000);

t2 = (double)_tend.tv_sec + (double)_tend.tv_usec/(1000*1000);

return t2-t1;

}

ramhd
30-09-2007, 18:12
No se vuoi una risoluzione più bassa del secondo.

Perchè manca una funzionalità così importante?

cionci
30-09-2007, 18:39
Perchè manca una funzionalità così importante?
Perché la libreria standard del C implementa solo funzionalità comuni per tutti i sistemi operativi (visto appunto che deve essere standard). Per questo funzionalità come queste devono essere richieste alle API o alle system call del sistema operativo, come appunto avviene sia in Linux che in Windows.

fracarro
12-10-2007, 08:32
Per migliorare la risoluzione in ambiente Linux puoi usare la funzione gettimeofday (http://www.penguin-soft.com/penguin/man/2/gettimeofday.html?manpath=/man/man2/gettimeofday.2.inc):


static struct timeval _tstart, _tend;

static struct timezone tz;

void tstart(void)

{

gettimeofday(&_tstart, &tz);

}

void tend(void)

{

gettimeofday(&_tend,&tz);

}


double elapsedtime()

{

double t1, t2;

t1 = (double)_tstart.tv_sec + (double)_tstart.tv_usec/(1000*1000);

t2 = (double)_tend.tv_sec + (double)_tend.tv_usec/(1000*1000);

return t2-t1;

}


Salve ragazzi. Sono estremamente interessato all'argomento per motivi scientifici. Allora, io programm in C sotto linux e avrei bisogno di una funzione per il calcolo del tempo di CPU assegnato al processo. Per quanto riguarda la precisione mi vanno bene i secondi con 2 cifre decimali ma quello che mi interessa è che uno stesso codice lanciato su una stessa macchina in momenti differenti NON mi restituisca tempi differenti ( diciamo con una tolleranza di un secondo). La funzione gettimeofday è estremamente inefficiente a riguardo. L'ho lanciata due volte, la prima con un solo programma, la seconda con altri due programmi in esecuzione è il tempo è passato da 60 a 110 secondi.


Attualmente utilizzo queste altre due funzioni che mi sembrano più precise ma vorrei sapere se voi ne conoscete altre. (non voglio che il tempo speso dal sistema operativo per fare le sue cose o passare la cpu da un processo all'altro venga sommato al tempo dell'algoritmo).

double timer(){
struct tms hold;

times(&hold);
return (double)(hold.tms_utime) / (double) sysconf(_SC_CLK_TCK);
}


double timer2()
{
struct rusage r;

getrusage(0, &r);
return (double)(r.ru_utime.tv_sec+r.ru_utime.tv_usec/(double)1000000);
}


Le due funzioni restituiscono lo stesso tempo con uno scarto di 0.01. Fatemi sapere grazie.

cionci
12-10-2007, 08:36
Te vuoi il tempo CPU di ogni singolo processo ? Il tempo di CPU è diverso dal tempo reale. E' per questo che gettimeofday non ti funziona.

fracarro
12-10-2007, 09:05
Te vuoi il tempo CPU di ogni singolo processo ? Il tempo di CPU è diverso dal tempo reale. E' per questo che gettimeofday non ti funziona.

Esatto. A me interessa inserire nel codice C il calcolo del tempo di CPU trascorso dal momento in cui comincia a quello in cui mi stampa l'output. Ripeto le due funzioni che ho postato mi sembrano buone ma vorrei sapere se ne esistono altre che siano il meno possibile influenzate da quello che combina il sistema operativo (o altri programmi in esecuzione) durante l'esecuzione dell'algoritmo. Es. Se mentre gira il mio algoritmo ne lancio altri 3, ascolto la musica e leggo qualche file vorrei che il tempo di CPU calcolato non variasse di molti (un secondo-due secondi di tolleranza) rispetto a quello restituito quando l'algoritmo gira da solo.

fracarro
17-10-2007, 15:26
Nessuno mi può aiutare?

fracarro
18-10-2007, 16:31
Forse ho risolto il problema. A quanto pare l'hyperthreading dei processori intel può alterare (in base agli altri processi in running) il tempo di cpu. L'ho scoperto su un forum in cui veniva data questa risposta:

"Does your system have hyperthreading? (look at whether the siblings field
in /proc/cpuinfo is greater than one)
If yes, there is no way to accurately measure runtimes because the
(single-threaded) performance of your CPU depends on the other tasks
running. Just disable hyperthreading for these measurements."

Ora ho disabilitato l'hyperthreading e le cose sembrano andare meglio (devo ancora fare un analisi approfondita dei risultati). Comunque a differenza di prima non mi segnala che i tre processi occupano CONTEMPORANEAMENTE il 99% di cpu ( visto che ciò è impossibile dato che le cpu sono solo due) ma una ne occupa il 99% e gli altri due il 50% ognuno.

cionci
18-10-2007, 16:35
In effetti è abbastanza strano. Non mi ero mai trovato davanti a problemi di questo tipo legati all'HT, ma devo dire che lasciano davvero increduli. Speriamo che nella prossima reintroduzione di qualcosa di simile all'HT (è in roadmap) prendano le dovute precauzioni.

thewebsurfer
27-10-2007, 23:45
da newbbo potreste rispiegarmi semplicemente come funziona sta roba del cronometrare l'esecuzione?:fagiano:

mi date le righe da incollare?:stordita:

fracarro
29-10-2007, 08:48
da newbbo potreste rispiegarmi semplicemente come funziona sta roba del cronometrare l'esecuzione?:fagiano:

mi date le righe da incollare?:stordita:

Allora prima del main copia questo:

float timer(){
struct tms hold;

times(&hold);
return (double)(hold.tms_utime) / (double) sysconf(_SC_CLK_TCK);
}


Poi:

main(){

float t;

t = timer();

.... codice del tuo programma.....

t = timer() - t;

printf("Time: %.2f",t);


}

cionci
29-10-2007, 09:07
Ma questo funziona solo con Linux ;)

fracarro
29-10-2007, 09:50
Ma questo funziona solo con Linux ;)

Yes, ma thewebsurfer non ha specificato il sistema operativo usato. Per windows non ho idea di come fare.

thewebsurfer
29-10-2007, 17:59
Yes, ma thewebsurfer non ha specificato il sistema operativo usato. Per windows non ho idea di come fare.

ho winzoz:muro:

cionci
29-10-2007, 18:04
ho winzoz:muro:
Risoluzione temporale ? Secondi...millisecondi o cosa ?