2

I'm writing an application using C++ and OpenMP and I want to reliably (and correctly) measure time of execution of parts of it. I have reviewed a few options (Windows, TDM-GCC x64 4.8.1):

  1. omp_get_wproc and clock seem to do the job but documentation (in direct contradiction to actual behavior) says that they measure total time resources consumed by given process (that is, e.g. one second with two working threads counts as two seconds). The "correct" behavior is not what I want,
  2. time/difftime don't have enough resolution,
  3. GetProcessTime (WinAPI) does what clock should do and is platform-specific,
  4. QueryPerformanceCounter (WinAPI) seems to be the way to go but is platform-specific,
  5. C++11 high_resolution_clock works ok but it's a part of a new standard.

My question, primarily, is: how do people doing scientific computing do this, and why do it that way? And, is the behavior of clock a bug in my implementation of standard library or a too popular misconception?

EDIT: Small explanation: I'm a bit hesitant to use C++11 because I'll probably run my code on a cluster with somewhat old software.

matb
  • 227
  • 2
  • 7
  • W.r.t the new standard and `high_resolution_clock` is the code required to be compatible with C++03? – Niall Oct 01 '14 at 12:38
  • You could also take a look at boost::chrono, it provides a somewhat convenient wrapper for whatever happens to be currently available. – ecotax Oct 01 '14 at 12:45
  • right, I've actually taken a look at boost::chrono to find that for Windows it actually uses QueryPerformanceCounter – matb Oct 01 '14 at 16:43

2 Answers2

3

Copied directly from my current research project:

#include <chrono>
#include <type_traits>

/** @brief Best available clock. */
using clock_type = typename std::conditional<
  std::chrono::high_resolution_clock::is_steady,
  std::chrono::high_resolution_clock,
  std::chrono::steady_clock>::type;

We want to measure wall time, not user-space CPU cycles to be fair and account for the multi-threading overhead as well. Unfortunately, many implementations define high_resolution_clock as an alias for real_time_clock which would spoil our results in case the system time is adjusted during our measurements.

Yes, std::chrono is a C++11 feature but if this is research as you say, what stops you from using the most modern compiler? You won't need your code to compile on the most weird platform that might exist somewhere in some dusty cellar of a customer. Anyway, if you just cannot have C++11, you can easily implement these clocks yourself. They are (at least in GNU libstdc++) just thin wrappers around clock_gettime.

5gon12eder
  • 24,280
  • 5
  • 45
  • 92
  • On this typeswitch : Typically `high_resolution_clock` is a typedef for either `system_clock` or `steady_clock`. So to trace that `std::conditional` if the `is_steady` part is true, then you pick the `high_resolution_clock` which is (a typedef to) the `steady_clock`. If it's false then you pick the `steady_clock` again. Just use `steady_clock` from the beginning ... – Nikos Athanasiou Feb 26 '16 at 00:03
  • 1
    @NikosAthanasiou While this might “typically” be the case, the standard does not mandate it. `std::chrono::{system,steady,high_resolution}_clock` *may* be implemented as three different clocks. That's not to say that `steady_clock` isn't a decent choice in practice. – 5gon12eder Feb 26 '16 at 00:23
  • N.B you should also find a way, for you and users of your code, to avoid non-portably mixing time points of different clocks (if ever this type switch acquires a meaning, it'll behave differently on different platforms) – Nikos Athanasiou Feb 29 '16 at 20:46
1

You didn't mention boost::chrono. Same as C++11 chrono, but works with C++03 compiler.

Also, I cannot understand your hesitation about C++11. We are almost in 2015, and C++11 is not that new. It is even not the most recent standard. So, #include <chrono> is a way to go.

Note however, that chrono is somewhat broken in Visual Studio 2013 Standard library implementation. I, personally, use std::chrono everywhere and swap it to boost::chrono via conditional defines and typedefs. Hope they'll fix it in Visual Studio Next.

Ivan Aksamentov - Drop
  • 12,860
  • 3
  • 34
  • 61
  • Oh yes, Boost is probably an even better choice than doing the system calls yourself. At least if Boost already is a dependency of your project. – 5gon12eder Oct 01 '14 at 12:46
  • @5gon12eder Fair enough. Even worse. Actually, to use boost you would need two compiled libs: `boost_chrono` and `boost_system`. Though, if we're talking about cross-platform threading with C++03 we, probably, already have `boost::thread` and `boost::system` as dependencies, so `boost::chrono` fits just well here. – Ivan Aksamentov - Drop Oct 01 '14 at 12:54