zarko
zarko

Reputation: 47

Strange clock() behaviour

Could someone explain this clock() (time_h) behaviour:

clock_t start, stop;
long i;
double t = 0.;
for(i = 0; i < 10e7; i++){
    start = clock();
    //nothing
    stop = clock();
    t = t + (double)(stop - start) / CLOCKS_PER_SEC;
}
printf("t: %fs\n", t);

Output:

t: 12.883712s

I suppose that the reason could be the accumulation of small t values caused by clock() error. Is there a way to deal with that?

Update: Just to explain 'real world' situation, because there are a lots of suggestions. //nothing is a block of code which time interval is very small (probably in nanoscale) and instead of one loop there are few of them which are also hard to measure.

Upvotes: 2

Views: 400

Answers (3)

rodrigo
rodrigo

Reputation: 98338

You cannot measure very short timespans with clock() (or for that matter, with any other method unless you use a real-time OS and a lot of care).

Adding up a lot of small measurements is not a good idea, because granularity problems may accumulate. It is far better to measure the big loop and divide by the number of iterations:

clock_t start, stop;
long i, num_iter = 1e8;
start = clock();
for(i = 0; i < num_iter; i++){
    //whatever
}
stop = clock();
t = (double)(stop - start) / num_iter / CLOCKS_PER_SEC;
printf("t: %fs\n", t);

If you feel that the time of //whatever is too short, just increate the number of iterations!

But what if the loop code has two parts: one to prepare the data, another one is the real code you want to measure? ...and you cannot run the real code without the preparation phase. Or simply, what if the code I want to measure is very short and the loop overhead is too significant?

Then one way to do it is to run the measurement twice, one of them bypassing the to-be-measured code, and then calculate the difference:

clock_t start, time1, time2;
long i, num_iter = 1e8;
double t;

start = clock();
for(i = 0; i < num_iter; i++){
    prepare_algoritm();
}
time1 = clock() - start;

start = clock();
for(i = 0; i < num_iter; i++){
    prepare_algoritm();
    run_algorith();
}
time2 = clock() - start;

t = (double)(time2 - time1) / num_iter / CLOCKS_PER_SEC; 
printf("run_algorithm time: %fs\n", t);

Upvotes: 1

Bathsheba
Bathsheba

Reputation: 234635

The answer you're getting is reasonable, since the compiler can't optimise out the clock() calls and I don't see calls to clock() as being particularly cheap.

But your measurement is numerically inaccurate - I think your approach underestimates the total. Try

clock_t start, stop;
clock_t total = 0;
for (long/*don't overflow a 16 bit int*/ i = 0; i < 10e7; i++){
    start = clock();
    stop = clock();
    total += stop - start
}
double t = 1.0 * total / CLOCKS_PER_SEC;
printf("t: %fs\n", t);

instead. That is, perform the division at the end.

You could, in a sense, calibrate the overhead using

start = clock();
/*ToDo - the real code*/
stop = clock();
control = clock();
/*Time is (stop - start) - (control - stop)*/

Upvotes: 3

pcarter
pcarter

Reputation: 1618

Consider the following modification of your program:

#include <time.h>
#include <stdio.h>

int main( int argc, char *argv[]) {
  clock_t start, stop;
  int i;
  double t = 0.;
  int n = atoi(argv[1]);
  int cnt = 0;
  for(i = 0; i < n; i++){
    start = clock();
    //nothing
    stop = clock();
    if ( start != stop) {
      printf( "%d %d\n", start, stop);
      cnt++;
    }
    t = t + (double)(stop - start) / CLOCKS_PER_SEC;
  }
  printf("t: %gs %g %d\n", t, t/n, cnt);
  return 0;
}

And the output for two runs

$ ./a.out 1000000
30000 40000
70000 80000
90000 100000
110000 120000
170000 180000
180000 190000
220000 230000
230000 240000
240000 250000
250000 260000
260000 270000
270000 280000
t: 0.12s 1.2e-07 12

$ ./a.out 100000
t: 0s 0 0

This shows that you are getting non-zero values because when you run the loop enough times the start and end values are different because occasionally one runs right before the clock time is about to change and so the second call returns a different value. When this happens t will increase.

Upvotes: 0

Related Questions