clock() probléma

Fórumok

Szeretném egy programrészlet futásidejét mérni (másodpercben). A következőket próbáltam:


clock_t t1=clock();
...
egyéb utasítások
...
clock_t t2=clock();

masodperc=(t2-t1)/CLOCKS_PER_SEC;

A probléma az, hogy a t1, t2 csak long értéket (úgy tudom, hogy clock_t is long(?), ill. a clock() long-al tér vissza) hajlandó elfogadni, amivel nem sokra megyek, mert nem tudok vele osztani legalábbis nekem nem ad tizedestörtet az itt is látható kódrészlet utolsó sora, ill. ha 1-nél kisebb, 0-nak veszi. Több helyen láttam kényszerített típuskonverziós megoldásokat, mint pl:


masodperc=((double)(t2-t1))/CLOCKS_PER_SEC;

vagy:

masodperc=((double)(t2-t1)/CLOCKS_PER_SEC);

de nekem nem működtek, ill. ha ezek nélkül próbéltam akkor a már leírt jelenséget muatta, ezzel pedig (ebben az esetben a "masodperc" változó értelemszerűen double) lehetetlen (pl. negatív) értékeket adott.

Van esetleg valakinek ötlete, mi lehet a hiba?

Hozzászólások


nyos@nyos:~/src$ cat idoeltelik.c
#include <time.h>
#define N 30000

main()
{
  clock_t t0,t1;
  int i,j,k;
  double ido;

  t0=clock();
  /////////////// csinalunk valamit /////////////
  for(i=0;i<N;i++)
    for(j=0;j<N;j++)
      if(i<j)
        k++;
  ///////////////////////////////////////////////
  t1=clock();

  ido=t1-t0;
  ido/=CLOCKS_PER_SEC;
  printf("%ld - %ld\n",t0,t1);
  printf("%lf\n",ido);
  printf("%lf\n",((double)(t1-t0))/CLOCKS_PER_SEC);
}
nyos@nyos:~/src$ time ./a.out
0 - 2220000
2.220000
2.220000

real    0m2.250s
user    0m2.228s
sys     0m0.004s

Gyakorlatilag 1:1-ben a te kodod, es nalam mukodik..
Milyen nagysagrendu az, amit mersz?
Ha tul kicsi, nem jo. Ez csak egy kozelitest ad.
Ha tul nagy (mondjuk 20-30 perc), az alatt a 32 bites szam korbefordulhat, es igy negativ szamot kapsz (a leirasa szerint 72 percenkent ugyanazt adja vissza).

Elobbi esetben probald meg a merendo kodot tobbszor lefuttatni egy ciklusban, hogy pontosabb eredmenyt kapj.
Utobbi esetben inkabb time-al inditsd el, es szedd ki a tobbi, lassito kodot a programodbol (bar ha csak azt akarod merni, akkor nem sokat szamit az inicializalas, csak a fo szamitas ideje).

Hasznos lehet meg a gnu profiler hasznalata.
gcc -pg opcioval kell forditani, utana a gprof-al elemezni
Kiirja, hogy melyik fuggvenyek hanyszor futottak le, atlagosan, es osszesen, illetve szazalekban melyik mennyi processzoridot igenyelt.
Ugyanezt kulon es rekurzivan is kiszamolja. (Egyik esetben a main-ben tolti a program az ido 100%-at, hiszen fut. Masik esetben csak amig tenylegesen a main-en van a vezerles.)
---------------------
int iPhone,iMac,iPod; // Apple using Hungarian notation :)

Nincs köze a jelen problémához, de esetleg érdemes lehet 'long long' típusban tartani a t1 és t2 értékeket.

Addig, amig csak kivonod őket egymásból, természetesen nincsen semmi baj, de ha mondjuk ki akarod írni a (printf) az értékeket, akkor máris fogalmad sincs hogy azon a gépen, ahol majd a programot valaki valamikor fordítani akarja, '%lu' '%llu' vagy valami más lesz-e a megfelelő szekvencia.

Szerintem ha pontosabb ido"ziteseket es/vagy ido"intervallum-me're'seket csinalna'l, akkor ne a

clock()

-ot hasznald, hanem a

getrusage()

es/vagy

gettimeofday()

fuggvenyeket. Ezeknel tuti nem jon elo" az a hiba, hogy a visszateresi ertek (clock_t) platform-fuggo" legyen, illetve tulcsordulas sem lesz (ti. a clock() az kb. 72-73 perces periodussal ugyanazt az erteket adja vissza, tehat ha ennel hosszabb intervallumot akarsz me'rni, akkor a clock() semmikeppen sem lesz jo.

En erre csinaltam egy p'ar egyszerubb fv-t:


double get_user_time(void)
{
 struct rusage  ru;
 double         tm;
 getrusage(RUSAGE_SELF,&ru);
 tm=(double)ru.ru_utime.tv_sec+(double)ru.ru_utime.tv_usec/1000000.0;
 return(tm);
}
double get_real_time(void)
{
 struct timeval tv;
 double         tm;
 gettimeofday(&tv,NULL);
 tm=(double)tv.tv_sec+(double)tv.tv_usec/1000000.0;
 return(tm);
}

primko', de a celnak teljesen jol megfelel.

A.