54

I mean: how can I measure time my CPU spent on function execution and wall clock time it takes to run my function? (Im interested in Linux/Windows and both x86 and x86_64). See what I want to do (Im using C++ here but I would prefer C solution):

int startcputime, endcputime, wcts, wcte;

startcputime = cputime();
function(args);
endcputime = cputime();

std::cout << "it took " << endcputime - startcputime << " s of CPU to execute this\n";

wcts = wallclocktime();
function(args);
wcte = wallclocktime();

std::cout << "it took " << wcte - wcts << " s of real time to execute this\n";

Another important question: is this type of time measuring architecture independent or not?

yak
  • 3,770
  • 19
  • 60
  • 111
  • I realize you want to do this programmatically in code, but here goes anyway: http://superuser.com/questions/228056/windows-equivalent-to-unix-time-command – Son-Huy Pham Jul 02 '13 at 17:57
  • @Huytard: thanks:) I know `time` in linux but as you wrote, I need to do it directly in C code – yak Jul 02 '13 at 17:59
  • @yak On Windows, `clock()` gives wall time and `GetProcessTimes` gives cpu time. On Linux `gettimeofday()` gives wall time, and `clock()` gives cpu time. – Mysticial Jul 02 '13 at 18:11
  • @Mysticial: huh! so its a little bit complicated! I will try to write some code and paste results later (for both win/lin). But any other answer is welcome! :) – yak Jul 02 '13 at 18:12
  • 2
    If you can use C++, `boost::auto_cpu_timer` (http://boost.org/libs/timer) is what you need. Your code becomes `boost::auto_cpu_timer t; function(args);` (yeah no cout, nothing and thats it, you get wall and cpu — I like this feature). – lip Jul 02 '13 at 18:15
  • FWIW, OpenMP has a `omp_get_wtime()` timer that measures wall time and is of fairly high resolution. – Mysticial Jul 02 '13 at 18:18
  • I actually have both of wallclock and cpuclocks encapsulated in an API for one of my programs (for both Windows + Linux). If nobody gives a complete answer before I get back from work, I'll post it here. – Mysticial Jul 02 '13 at 18:20
  • Once I have faced the difficulty that clock() may be easily overflowed. clock_t was a 4 byte signed integer. Its maximum value was 2^31=2.147e9. CLOCKS_PER_SEC was 1000 in Windows and 1000000 in Linux. So, the maximum time was 24.8 days in Windows and 35.8 min in Linux. – Sergey Oct 12 '15 at 18:49

4 Answers4

72

Here's a copy-paste solution that works on both Windows and Linux as well as C and C++.

As mentioned in the comments, there's a boost library that does this. But if you can't use boost, this should work:

//  Windows
#ifdef _WIN32
#include <Windows.h>
double get_wall_time(){
    LARGE_INTEGER time,freq;
    if (!QueryPerformanceFrequency(&freq)){
        //  Handle error
        return 0;
    }
    if (!QueryPerformanceCounter(&time)){
        //  Handle error
        return 0;
    }
    return (double)time.QuadPart / freq.QuadPart;
}
double get_cpu_time(){
    FILETIME a,b,c,d;
    if (GetProcessTimes(GetCurrentProcess(),&a,&b,&c,&d) != 0){
        //  Returns total user time.
        //  Can be tweaked to include kernel times as well.
        return
            (double)(d.dwLowDateTime |
            ((unsigned long long)d.dwHighDateTime << 32)) * 0.0000001;
    }else{
        //  Handle error
        return 0;
    }
}

//  Posix/Linux
#else
#include <time.h>
#include <sys/time.h>
double get_wall_time(){
    struct timeval time;
    if (gettimeofday(&time,NULL)){
        //  Handle error
        return 0;
    }
    return (double)time.tv_sec + (double)time.tv_usec * .000001;
}
double get_cpu_time(){
    return (double)clock() / CLOCKS_PER_SEC;
}
#endif

There's a bunch of ways to implement these clocks. But here's what the above snippet uses:

For Windows:

For Linux:


And here's a small demonstration:

#include <math.h>
#include <iostream>
using namespace std;

int main(){

    //  Start Timers
    double wall0 = get_wall_time();
    double cpu0  = get_cpu_time();

    //  Perform some computation.
    double sum = 0;
#pragma omp parallel for reduction(+ : sum)
    for (long long i = 1; i < 10000000000; i++){
        sum += log((double)i);
    }

    //  Stop timers
    double wall1 = get_wall_time();
    double cpu1  = get_cpu_time();

    cout << "Wall Time = " << wall1 - wall0 << endl;
    cout << "CPU Time  = " << cpu1  - cpu0  << endl;

    //  Prevent Code Elimination
    cout << endl;
    cout << "Sum = " << sum << endl;

}

Output (12 threads):

Wall Time = 15.7586
CPU Time  = 178.719

Sum = 2.20259e+011
Mysticial
  • 464,885
  • 45
  • 335
  • 332
  • Thank you so much for this! Just two more questions: are those methods architecture-independent? Is it possible to do the same thing (get cpu and wall time) using inline asseembly (and function like, lets say, `rdtsc`?) – yak Jul 03 '13 at 14:20
  • 1
    @yak It shouldn't be. They are OS-specific. And Windows probably uses `rdtsc()` to implement the performance counters. But if it were on a different architecture, it would be the OS's job to implement those functions. As far as doing these in inline assembly, it's tricky. Note that `rdtsc()` by itself isn't enough to get wall time since you still need something to give you how many ticks there are in a second. And I'm not aware of anything outside the OS that can give you CPU time. – Mysticial Jul 03 '13 at 15:09
  • is the elapsed time (wall1 - wall0) in seconds ? – dynamic Jan 26 '14 at 11:31
  • 1
    @llnk Yes, they're all in seconds. – Mysticial Jan 26 '14 at 11:31
  • 1
    `clock()` works fine on Linux, but does not include the time spent in child processes (e.g., started by a `system()` call). If you need to also measure the time spent in the child processes, have a look at `times()`, which gives you cpu time and system time for the current process and for the child processes. Note that the clocks per second is not `CLOCKS_PER_SEC` here, but rather `sysconf(_SC_CLK_TCK)`. – farindk Jul 21 '14 at 10:07
  • Be careful with QueryPerformanceCounter because it can leap forward unexpectedly by several seconds, so you have to compare it constantly with GetTickCount: [Microsoft KB274323](http://support.microsoft.com/kb/274323/en-gb). – Tyler Streeter Sep 24 '14 at 14:10
  • Great answer. However, for your Linux/Posix versions, you have to `#include ` or `` as well in order to use the `clock()` function and `CLOCKS_PER_SEC`. – NoseKnowsAll Jun 09 '15 at 20:34
  • Exact same code on my windows machine (64-bit) running a cuda code: Wall Time = 0.251269 CPU Time = 0.0625 why the opposite? I expected CPU time to be bigger. There are some child threads spawned too. If I run nvidia visual profiler, then CPU time becomes zero while wall stays same. – huseyin tugrul buyukisik Feb 10 '18 at 21:08
  • @huseyintugrulbuyukisik I don't know much about CUDA. But if it's CPU, then it sounds like the process is getting blocked or tasked out. – Mysticial Feb 11 '18 at 00:12
38

C++11. Much easier to write!

Use std::chrono::system_clock for wall clock and std::clock for cpu clock http://en.cppreference.com/w/cpp/chrono/system_clock

#include <cstdio>
#include <ctime>
#include <chrono>

.... 

std::clock_t startcputime = std::clock();
do_some_fancy_stuff();
double cpu_duration = (std::clock() - startcputime) / (double)CLOCKS_PER_SEC;
std::cout << "Finished in " << cpu_duration << " seconds [CPU Clock] " << std::endl;


auto wcts = std::chrono::system_clock::now();
do_some_fancy_stuff();
std::chrono::duration<double> wctduration = (std::chrono::system_clock::now() - wcts);
std::cout << "Finished in " << wctduration.count() << " seconds [Wall Clock]" << std::endl;

Et voilà, easy and portable! No need for #ifdef _WIN32 or LINUX!

You could even use chrono::high_resolution_clock if you need more precision http://en.cppreference.com/w/cpp/chrono/high_resolution_clock

carlduke
  • 560
  • 6
  • 10
16

To give a concrete example of @lip's suggestion to use boost::timer if you can (tested with Boost 1.51):

#include <boost/timer/timer.hpp>

// this is wallclock AND cpu time
boost::timer::cpu_timer timer;

... run some computation ...

boost::timer::cpu_times elapsed = timer.elapsed();
std::cout << " CPU TIME: " << (elapsed.user + elapsed.system) / 1e9 << " seconds"
          << " WALLCLOCK TIME: " << elapsed.wall / 1e9 << " seconds"
          << std::endl;
Andre Holzner
  • 18,333
  • 6
  • 54
  • 63
  • Which one is the total time? – Tomáš Zato Nov 02 '15 at 16:08
  • 'total' in which sense ? CPU time is usually summed over all threads/cores (sum of how long each CPU core was busy executing the code), wallclock time is how long you had to wait until the code completes. For code running on more than one CPU core, CPU time can be larger than the wallclock time. – Andre Holzner Nov 02 '15 at 16:32
  • 1
    No you didn't figure out both are 'total' one is wall clock time and another one is cpu time. – Neel Basu Aug 04 '16 at 11:41
0

Use the clock method in time.h:

clock_t start = clock();
/* Do stuffs */
clock_t end = clock();
float seconds = (float)(end - start) / CLOCKS_PER_SEC;

Unfortunately, this method returns CPU time on Linux, but returns wall-clock time on Windows (thanks to commenters for this information).

syb0rg
  • 8,057
  • 9
  • 41
  • 81
  • and it gives me which time? wall clock time or cpu time? – yak Jul 02 '13 at 18:08
  • It measures CPU time, not wall-clock time if that is what you are looking for. – syb0rg Jul 02 '13 at 18:09
  • 3
    @syb0rg Actually, `clock()` gives cpu time on Linux, and wall time on Windows. – Mysticial Jul 02 '13 at 18:09
  • Im looking for both;) cheers for this, so now I have to look for just a wall clock time :P – yak Jul 02 '13 at 18:10
  • @Mysticial: are you 100% sure? can you give any code samples (for win/lin)? any docs about this issue? – yak Jul 02 '13 at 18:10
  • @yak Just try it. You'll see that `clock()` gives real time regardless of thread activity. – Mysticial Jul 02 '13 at 18:12
  • @Mysticial I was misinformed, sorry. Leave it up to Windows to screw with things. – syb0rg Jul 02 '13 at 18:13
  • 3
    @syb0rg: `clock()` is supposed to return CPU time as per ISO standard; MS [documention](http://msdn.microsoft.com/en-us/library/4e2ess30.aspx) clearly states that it returns wall-clock time in Windows, though... – Christoph Jul 02 '13 at 18:14