3

What is the most accurate way to calculate the elapsed time in C++? I used clock() to calculate this, but I have a feeling this is wrong as I get 0 ms 90% of the time and 15 ms the rest of it which makes little sense to me.

Even if it is really small and very close to 0 ms, is there a more accurate method that will give me the exact the value rather than a rounded down 0 ms?

clock_t tic = clock();

/*
  main programme body
*/

clock_t toc = clock();
double time = (double)(toc-tic);
cout << "\nTime taken: " << (1000*(time/CLOCKS_PER_SEC)) << " (ms)";

Thanks

user2550888
  • 293
  • 1
  • 9
  • 18
  • 1
    You should add the Operating System on which your code is running as higher resolution timers are mostly OS dependent. If you use C++11 you should consider havong a look at the header, which provides higher resolution timers and wraps OS dependencies.\ – ogni42 Jul 15 '13 at 13:37
  • Chrono uses rdtsc counter too? – huseyin tugrul buyukisik Jul 15 '13 at 13:39
  • I'm running XP 32 bit – user2550888 Jul 15 '13 at 13:39
  • 2
    @huseyintugrulbuyukisik: `RDTSC` actually is not a good source for wall clock time on today's computers. For one thing, it isn't necessarily synchronized between cores, so subtracting two values is meaningless if your process got rescheduled to a different core. Also, CPU today have dynamic clock rates which respond to load. For measuring complexity of an algorithm, pinning a thread to a single CPU and using `RDTSC` is helpful. For timestamps / measuring wall time, definitely not. – Ben Voigt Jul 15 '13 at 13:44
  • @Ben Voigt For example, I wanted to see how good is an dot-product avx/sse intrinsic sequence performance, can I use RDTSC with some atomic locks or constraining the thread to single core as you say? I know that rdtsc takes nearly 50 cycles. – huseyin tugrul buyukisik Jul 15 '13 at 13:48
  • @huseyintugrulbuyukisik: Dynamic frequencies may still mess with the relationship between CPU cycles and memory latency. But RDTSC will give reasonable results in that case. To do better, you'd need Intel's own profiler that monitors CPU, cache behavior, and memory access as separately reported metrics. – Ben Voigt Jul 15 '13 at 13:51
  • 1
    @huseyintugrulbuyukisik: As far as `RDTSC` being an expensive operation, it's likely that you have a platform that does synchronize between cores. Reading an HPET is slow too. – Ben Voigt Jul 15 '13 at 13:52

3 Answers3

8

With C++11, I'd use

#include <chrono>
auto t0 = std::chrono::high_resolution_clock::now();
...
auto t1 = std::chrono::high_resolution_clock::now();
auto dt = 1.e-9*std::chrono::duration_cast<std::chrono::nanoseconds>(t1-t0).count();

for the elapsed time in seconds.


For pre 2011 C++, you can use QueryPerformanceCounter() on windows or gettimeofday() with linux/OSX. For example (this is actually C, not C++):

timeval oldCount,newCount;
gettimeofday(&oldCount, NULL);
...
gettimeofday(&newCount, NULL);
double t = double(newCount.tv_sec -oldCount.tv_sec )
         + double(newCount.tv_usec-oldCount.tv_usec) * 1.e-6;

for the elapsed time in seconds.

Walter
  • 44,150
  • 20
  • 113
  • 196
  • 1
    Except be careful on Visual Studio. – Bartek Banachewicz Jul 15 '13 at 13:44
  • @BartekBanachewicz I'm never on Visual Studio. What's wrong there? Doesn't it implement the standard properly? – Walter Jul 15 '13 at 13:45
  • [the comment says it all](http://stackoverflow.com/questions/13263277/difference-between-stdsystem-clock-and-stdsteady-clock/13266477#comment18098256_13266477) – Bartek Banachewicz Jul 15 '13 at 13:46
  • @BartekBanachewicz that comment is just a statement. where is the evidence? – Walter Jul 15 '13 at 13:52
  • 2
    @Walter: In case you're unaware, that comment was left by a Microsoft DevDiv employee. And [here is the bug](https://connect.microsoft.com/VisualStudio/feedback/details/719443) – Ben Voigt Jul 15 '13 at 13:53
  • @BartekBanachewicz Thanks, I was indeed unaware (as I've said, I don't use visual studio, but the recent versions of gcc, clang, icpc) – Walter Jul 15 '13 at 13:57
  • Thanks for the quick response. I don't think I have C++11 as I can't compile that code. Is chrono only available for C++11? – user2550888 Jul 15 '13 at 14:00
  • @user2550888 did you enable c++11? With gcc, for example, you must add the option `-std=c++0x` (version 4.7 and earlier) or `std=c++11` (version 4.8 and later), same for clang++. – Walter Jul 15 '13 at 14:06
  • Thank you, the QueryPerformanceCounter example below worked for me - http://stackoverflow.com/questions/1739259/how-to-use-queryperformancecounter – user2550888 Jul 15 '13 at 14:28
  • @walter, You must use C-like cast for this to be really C: `(double)(a-b)` instead of `double(a-b)`. – Guilherme Bernal Jul 15 '13 at 14:38
3

std::chrono::high_resolution_clock is as portable a solution as you can get, however it may not actually be higher resolution than what you already saw.

Pretty much any function which returns system time is going to jump forward whenever the system time is updated by the timer interrupt handler, and 10ms is a typical interval for that on modern OSes.

For better precision timing, you need to access either a CPU cycle counter or high precision event timer (HPET). Compiler library vendors ought to use these for high_resolution_clock, but not all do. So you may need OS-specific APIs.

(Note: specifically Visual C++ high_resolution_clock uses the low resolution system clock. But there are likely others.)

On Win32, for example, the QueryPerformanceFrequency() and QueryPerformanceCounter() functions are a good choice. For a wrapper that conforms to the C++11 timer interface and uses these functions, see

Community
  • 1
  • 1
Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
0

If you have C++11 available, use the chrono library.

Also, different platforms provide access to high precision clocks.

For example, in linux, use clock_gettime. In Windows, use the high performance counter api.

Example:

C++11:

auto start=high_resolution_clock::now();
...  // do stuff
auto diff=duration_cast<milliseconds>(high_resolution_clock::now()-start);
clog << diff.count() << "ms elapsed" << endl;
jsp
  • 1,225
  • 11
  • 21
  • Thanks for the quick response. I don't think I have C++11 as I can't compile that code. Is chrono only available for C++11? – user2550888 Jul 15 '13 at 13:57
  • what compiler are you using? you may have to enable c++11 support. for example, using g++, you have to call with `-std=c++11 or -std=c++0x`. – jsp Jul 16 '13 at 15:10