Helsinki University of Technology



Sama Suomeksi


Front Page

Overview

Schedule

Lectures

Guides

Topics

Teachers


T-106.290 Ohjelmoinnin laboratoriotyöt

How to Measure CPU Time.

This document gives a few tricks of how to measure time.

The times(2) should be present in all POSIX-conformant systems. It returns the number of system clock ticks (often units of 10 milliseconds) since some point in time and fills the passed struct tms with other similar information. Read the manual page for more information.

Here's a sample program of how to use times:

    #include <stdio.h>
    #include <unistd.h>
    #include <sys/times.h>

    double give_time(void)
    {
      struct tms tms;
      long ticks_per_second, ticks;
  
      ticks = times(&tms);
      if (ticks == -1) {
        fprintf(stderr, "'times' failed\n");
        exit(1);
      }
      ticks_per_second = sysconf(_SC_CLK_TCK);
      if (ticks_per_second == -1) {
        fprintf(stderr, "'sysconf(_SC_CLK_TCK)' failed.\n");
        exit(1);
      }
      return ticks / (double) ticks_per_second;
    }

    int fib(int n)
    {
      return n < 2 ? 1 : fib(n-1) + fib(n-2);
    }

    int main(int argc, char **argv)
    {
      int f;
      double start_time;

      start_time = give_time();
      printf("fib(40) = %d\n", fib(40));
      printf("duration = %f seconds\n", give_time() - start_time);
      return 0;
    }
         

When executed the output code look something like this:

    fib(40) = 165580141
    duration = 12.340000 seconds
	   

The main drawback of times(2) is that its granularity of measurement is usually rather large. Most processors, however, have various counters that can be used to measure time much more accurately. Unfortunately this requires going down to assembler programming. Below some code that assumes the GNU c compiler, gcc:

	   
    #include <stdio.h>

    #ifdef __GNUC__
    #ifdef __i386__
    /* Requires a Pentium or newer. */
    #define TICKS(t)  asm volatile ("rdtsc" : "=a" (t) : : "edx")
    #endif

    #ifdef __sparc_v9__
    /* The #ifdef above is not fully reliable.  Please pass
       `-mcpu=ultrasparc' to the compiler or `-xarch=v8plusa' to the
       assembler. */
    #define TICKS(t)  asm volatile("rd %%tick,%0" : "=r" (t))
    #endif

    #ifdef PPC
    #define TICKS(t)  asm volatile("mfspr %0,268" : "=r" (t))
    #endif
    #endif /* __GNUC__ */
    
    #ifndef TICKS
    #define TICKS(t)  do { (t) = 0; } while (0)
    #endif


    int fib(int n)
    {
      return n < 2 ? 1 : fib(n-1) + fib(n-2);
    }

    int main(int argc, char **argv)
    {
      int f;
      unsigned long start_time, end_time;

      TICKS(start_time);
      f = fib(4);
      TICKS(end_time);
      printf("fib(4) = %d\n", f);
      printf("duration = %lu ticks\n", end_time - start_time);
      return 0;
    }

Unfortunately the value assigned by TICKS to the argument variable is not specified. In Pentia it is the processor clock cycle counter, and therefore depends on the machine you use. In some cases, if you're only interested in the relative performance of algorithms, this might not really matter. But otherwise you may have to calibrate the values assigned by TICKS with the values returned by times(2). This is left for you to do.

Note also that the value assigned by TICKS may overflow and it too may be susceptible to time used by other processes.



Course email: cessu@cs.hut.fi
Kurssin newsgroup: opinnot.tik.labratyot
This page has been last updated on 2005-01-11.