SHANG ZHOU
SHANG ZHOU

Reputation: 67

Why the execution time of the same code on the same computer could be different?

I am new to C programming, I wrote code and want to get it's runtime. Here is what I did it. Every time I run my code, I get a different run time value. Is it right? or is something wrong with my code?

int main(int argc, char *argv[])
{
    time_t start,end;
    start=clock();
    // this part is some operation

    end=clock();
    int running_time=end-start;
    printf("Time taken: %d",running_time);
    return 0;
}

Upvotes: 6

Views: 8673

Answers (3)

Alain Merigot
Alain Merigot

Reputation: 11567

It depends on the variations that you observe. In modern computers, all is designed to statistically optimize the average run time. But many architectural features are based on statistic and depending on the initial conditions can lead to very different run times. This includes mostly caches and branch predictors. It is normal to have variations around 20-30% in runtime. And we did experiments on baremetal OSless systems and the same behavior stands.

Here is a program that measures times with the time stamp counter (cycles). Two simple functions can be tested. One is just zero a vector and the second is a set of tests on a random (but always identical) vector.

#include <stdio.h>
#include <stdlib.h>
#define N 1000000
#define TYPE int
#define ZERO 0

static unsigned long long start_timer() ;
static unsigned long long stop_timer() ;
static double dtime(long long debut, long long fin);


#ifdef __i386__
#  define RDTSC_DIRTY "%eax", "%ebx", "%ecx", "%edx"
#elif __x86_64__
#  define RDTSC_DIRTY "%rax", "%rbx", "%rcx", "%rdx"
#else
# error unknown platform
#endif


static inline unsigned long long start_timer() 
{ 
  unsigned int hi = 0, lo = 0; 

  asm volatile("cpuid\n\t"
           "rdtscp\n\t"
           "mov %%edx, %0\n\t"
           "mov %%eax, %1\n\t" 
           : "=r" (hi), "=r" (lo)
           :: RDTSC_DIRTY);      
  unsigned long long that =   (unsigned long long)((lo) |
                           (unsigned long long)(hi)<<32);

  return that; 
} 

static inline unsigned long long stop_timer() 
{ 
  unsigned int hi = 0, lo = 0; 

  asm volatile("rdtscp\n\t"    
           "mov %%edx, %0\n\t" 
           "mov %%eax, %1\n\t" 
           "cpuid\n\t"     
           : "=r" (hi), "=r" (lo)
           :: RDTSC_DIRTY);      
  unsigned long long that =   (unsigned long long)((lo) |
                           (unsigned long long)(hi)<<32);

  return that; 
} 

static inline double dtime(long long start, long long end)
{
  return (double) (end - start) ;
}


TYPE BF[N] ;

long long start, end;
double benchtime;


void zero(){
  int i, j, m ;
  start=start_timer();
  for (i=0;i<N;i++)
    BF[i]=ZERO;
  benchtime=dtime(start, stop_timer());

  printf ("%g\n", benchtime);
}

void randtest(){
  int i, j, m ;
  srandom(100);
  for (i=0;i<N;i++)
    BF[i]=random();
  int count=0;
  start=start_timer();
  for (i=0;i<N;i++){
    if (BF[i]>RAND_MAX/2)
      count++;
  }
  benchtime=dtime(start, stop_timer());

  printf ("%g\n", benchtime);
}



void main()
{
  #ifdef ZEROTEST
  zero();
  #else
  randtest();
  #endif
} 

Here are the results:

am@Mandel:~/tmp/d$ cc -DZEROTEST time.c ; for i in 1 2 3 4 5 6 7 8 9 10; do ./a.out; done

1.09084e+07 1.14298e+07 1.07197e+07 1.26519e+07 1.32742e+07 1.37184e+07 1.54689e+07 1.36335e+07 1.20818e+07 1.12298e+07

am@Mandel:~/tmp/d$ cc -DZEROTEST -O time.c ; for i in 1 2 3 4 5 6 7 8 9 10; do ./a.out; done

4.30112e+06 4.37242e+06 4.28102e+06 4.51831e+06 4.45952e+06 5.77813e+06 6.33686e+06 5.44415e+06 5.67434e+06 5.90118e+06

am@Mandel:~/tmp/d$ cc time.c ; for i in 1 2 3 4 5 6 7 8 9 10; do ./a.out; done

2.4763e+07 2.77489e+07 2.78568e+07 3.3762e+07 3.56298e+07 3.66709e+07 3.22833e+07 2.68651e+07 2.88412e+07 2.92287e+07

am@Mandel:~/tmp/d$ cc -O time.c ; for i in 1 2 3 4 5 6 7 8 9 10; do ./a.out; done

1.00543e+06 1.15819e+06 1.00544e+06 2.74409e+06 1.17561e+06 1.40751e+06 2.41898e+06 1.65623e+06 2.19502e+06 1.59414e+06

As you can see, it is common to have at least 30% time variation, but when branch predictors are concerned it can be much larger. And it happens in either optimize or unoptimized code.

You cannot consider that execution is something deterministic in modern architectures. There are variations due to architectural design choices that are at least as important as OS effects. And this is a major difficulty when real time is concerned.

Upvotes: 2

Muhammad Azam
Muhammad Azam

Reputation: 564

Nothing wrong with code. Its just understanding of OS scheduler for your program execution, It varies all time.

Upvotes: 5

Alonso Mondal
Alonso Mondal

Reputation: 64

It is very normal for run time to vary, as your computer is probably running many things (including your OS), not only that piece of code, and this will affect clock speeds.

On a computer where the processing consumption is very stable, run time should remain similar though.

There is nothing wrong with your code.

Upvotes: 2

Related Questions