MCKL
Monte Carlo Kernel Library
stop_watch.hpp
Go to the documentation of this file.
1 //============================================================================
2 // MCKL/include/mckl/utility/stop_watch.hpp
3 //----------------------------------------------------------------------------
4 // MCKL: Monte Carlo Kernel Library
5 //----------------------------------------------------------------------------
6 // Copyright (c) 2013-2018, Yan Zhou
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions are met:
11 //
12 // Redistributions of source code must retain the above copyright notice,
13 // this list of conditions and the following disclaimer.
14 //
15 // Redistributions in binary form must reproduce the above copyright notice,
16 // this list of conditions and the following disclaimer in the documentation
17 // and/or other materials provided with the distribution.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
20 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 // POSSIBILITY OF SUCH DAMAGE.
30 //============================================================================
31 
32 #ifndef MCKL_UTILITY_STOP_WATCH_HPP
33 #define MCKL_UTILITY_STOP_WATCH_HPP
34 
35 #include <mckl/internal/common.hpp>
36 #include <chrono>
37 #include <ratio>
38 
39 namespace mckl {
40 
41 namespace internal {
42 
43 #if MCKL_USE_RDPMC
44 
46 {
47  unsigned a = 0;
48  unsigned d = 0;
49  unsigned c = 0x40000001;
50  __asm__ volatile("rdpmc" : "=a"(a), "=d"(d) : "c"(c));
51 
52  return (static_cast<std::uint64_t>(d) << 32) + a;
53 }
54 
56 {
57  unsigned a = 0;
58  unsigned d = 0;
59  unsigned c = 0x40000001;
60  __asm__ volatile("rdpmc" : "=a"(a), "=d"(d) : "c"(c));
61 
62  return (static_cast<std::uint64_t>(d) << 32) + a;
63 }
64 
65 #elif MCKL_USE_RDTSCP
66 
68 {
69  unsigned hi = 0;
70  unsigned lo = 0;
71  asm volatile(
72  "cpuid\n\t"
73  "rdtsc\n\t"
74  "mov %%edx, %0\n\t"
75  "mov %%eax, %1\n\t"
76  : "=r"(hi), "=r"(lo)::"%eax", "%ebx", "%ecx", "%edx");
77  return (static_cast<std::uint64_t>(hi) << 32) + lo;
78 }
79 
81 {
82  unsigned hi = 0;
83  unsigned lo = 0;
84  asm volatile(
85  "rdtscp\n\t"
86  "mov %%edx, %0\n\t"
87  "mov %%eax, %1\n\t"
88  "cpuid\n\t"
89  : "=r"(hi), "=r"(lo)::"%eax", "%ebx", "%ecx", "%edx");
90  return (static_cast<std::uint64_t>(hi) << 32) + lo;
91 }
92 
93 #elif MCKL_USE_RDTSC
94 
96 {
97  unsigned hi = 0;
98  unsigned lo = 0;
99  asm volatile(
100  "cpuid\n\t"
101  "rdtsc\n\t"
102  "mov %%edx, %0\n\t"
103  "mov %%eax, %1\n\t"
104  : "=r"(hi), "=r"(lo)::"%eax", "%ebx", "%ecx", "%edx");
105  return (static_cast<std::uint64_t>(hi) << 32) + lo;
106 }
107 
108 inline std::uint64_t cycle_stop()
109 {
110  unsigned hi = 0;
111  unsigned lo = 0;
112  asm volatile(
113  "rdtsc\n\t"
114  "mov %%edx, %0\n\t"
115  "mov %%eax, %1\n\t"
116  "cpuid\n\t"
117  : "=r"(hi), "=r"(lo)::"%eax", "%ebx", "%ecx", "%edx");
118  return (static_cast<std::uint64_t>(hi) << 32) + lo;
119 }
120 
121 #else // MCKL_USE_RDPMC
122 
123 inline std::uint64_t cycle_start() { return 0; }
124 
125 inline std::uint64_t cycle_stop() { return 0; }
126 
127 #endif // MCKL_USE_RDPMC
128 
129 } // namespace internal
130 
131 MCKL_PUSH_CLANG_WARNING("-Wpadded")
135 template <typename WatchType>
137 {
138  public:
139  using watch_type = WatchType;
140 
141  StopWatchGuard(watch_type &watch, bool start = true)
142  : watch_(watch), start_(start)
143  {
144  if (start_) {
145  watch_.start();
146  }
147  }
148 
150  {
151  if (start_) {
152  watch_.stop();
153  }
154  }
155 
156  private:
157  watch_type &watch_;
158  const bool start_;
159 }; // class StopWatchGuard
161 
162 MCKL_PUSH_CLANG_WARNING("-Wpadded")
165 template <typename ClockType = std::chrono::high_resolution_clock>
167 {
168  public:
169  using clock_type = ClockType;
170 
172  : time_(0), cycles_(0), cycles_start_(0), running_(false)
173  {
174  reset();
175  }
176 
182  static constexpr bool has_cycles()
183  {
184 #if MCKL_USE_RDPMC || MCKL_USE_RDTSCP || MCKL_USE_RDTSC
185  return true;
186 #else
187  return false;
188 #endif
189  }
190 
196  bool running() const { return running_; }
197 
204  bool start()
205  {
206  if (running_) {
207  return false;
208  }
209 
210  running_ = true;
211  time_start_ = clock_type::now();
212  cycles_start_ = internal::cycle_start();
213 
214  return true;
215  }
216 
222  bool stop()
223  {
225  typename clock_type::time_point t = clock_type::now();
226 
227  if (!running_) {
228  return false;
229  }
230 
231  running_ = false;
232  cycles_ += c - cycles_start_;
233  time_ += t - time_start_;
234 
235  return true;
236  }
237 
239  void reset()
240  {
241  start();
242  time_ = typename clock_type::duration(0);
243  cycles_ = 0;
244  running_ = false;
245  }
246 
248  std::uint64_t cycles() const { return cycles_; }
249 
251  typename clock_type::duration const time() const { return time_; }
252 
254  template <typename Rep, typename Period>
255  Rep time() const
256  {
257  using time_type = std::chrono::duration<Rep, Period>;
258 
259  return std::chrono::duration_cast<time_type>(time_).count();
260  }
261 
263  double nanoseconds() const { return time<double, std::nano>(); }
264 
266  double microseconds() const { return time<double, std::micro>(); }
267 
269  double milliseconds() const { return time<double, std::milli>(); }
270 
272  double seconds() const { return time<double, std::ratio<1>>(); }
273 
275  double minutes() const { return time<double, std::ratio<60>>(); }
276 
278  double hours() const { return time<double, std::ratio<3600>>(); }
279 
280  private:
281  typename clock_type::duration time_;
282  typename clock_type::time_point time_start_;
283  std::uint64_t cycles_;
284  std::uint64_t cycles_start_;
285  bool running_;
286 }; // class StopWatchClockAdapter
288 
292 
293 } // namespace mckl
294 
295 #endif // MCKL_UTILITY_STOP_WATCH_HPP
double seconds() const
Equivalent to time<double, std::ratio<1>>()
Definition: stop_watch.hpp:272
bool start()
Start the watch, no effect if already started.
Definition: stop_watch.hpp:204
double hours() const
Equivalent to time<double, std::ratio<3600>>()
Definition: stop_watch.hpp:278
#define MCKL_PUSH_CLANG_WARNING(warning)
Definition: compiler.h:63
double nanoseconds() const
Equivalent to time<double, std::nano>()
Definition: stop_watch.hpp:263
ulong uint64_t
Definition: opencl.h:42
std::uint64_t cycle_start()
Definition: stop_watch.hpp:67
double microseconds() const
Equivalent to time<double, std::micro>()
Definition: stop_watch.hpp:266
bool running() const
If the watch is running.
Definition: stop_watch.hpp:196
std::uint64_t cycles() const
Return the accumulated cycles.
Definition: stop_watch.hpp:248
Rep time() const
Return the accumulated elapsed time in specified format.
Definition: stop_watch.hpp:255
bool stop()
Stop the watch, no effect if already stopped.
Definition: stop_watch.hpp:222
std::uint64_t cycle_stop()
Definition: stop_watch.hpp:80
static constexpr bool has_cycles()
If cycle counting is supported.
Definition: stop_watch.hpp:182
double milliseconds() const
Equivalent to time<double, std::milli>()
Definition: stop_watch.hpp:269
void reset()
Stop and reset the elapsed time to zero.
Definition: stop_watch.hpp:239
Start and stop a StopWatch in scope (similiar to a mutex lock guard)
Definition: stop_watch.hpp:136
Definition: mcmc.hpp:40
double minutes() const
Equivalent to time<double, std::ratio<60>>()
Definition: stop_watch.hpp:275
#define MCKL_POP_CLANG_WARNING
Definition: compiler.h:66
clock_type::duration const time() const
Return the accumulated elapsed time in its native format.
Definition: stop_watch.hpp:251
StopWatchGuard(watch_type &watch, bool start=true)
Definition: stop_watch.hpp:141
StopWatch as an adapter of C++ standard library compatible clock.
Definition: stop_watch.hpp:166