QMCPACK
NewTimer.h
Go to the documentation of this file.
1 //////////////////////////////////////////////////////////////////////////////////////
2 // This file is distributed under the University of Illinois/NCSA Open Source License.
3 // See LICENSE file in top directory for details.
4 //
5 // Copyright (c) 2020 QMCPACK developers.
6 //
7 // File developed by: Ken Esler, kpesler@gmail.com, University of Illinois at Urbana-Champaign
8 // Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
9 // Jeremy McMinnis, jmcminis@gmail.com, University of Illinois at Urbana-Champaign
10 //
11 // File created by: Ken Esler, kpesler@gmail.com, University of Illinois at Urbana-Champaign
12 //////////////////////////////////////////////////////////////////////////////////////
13 
14 
15 /** @file NewTimer.h
16  * @brief NewTimer class various high-resolution timers.
17  */
18 #ifndef QMCPLUSPLUS_NEW_TIMER_H
19 #define QMCPLUSPLUS_NEW_TIMER_H
20 
21 #include <string>
22 #include <algorithm>
23 #include <map>
24 #include "config.h"
25 #include "Clock.h"
26 
27 #ifdef USE_VTUNE_TASKS
28 #include <ittnotify.h>
29 #endif
30 
31 #ifdef USE_NVTX_API
32 #include <nvToolsExt.h>
33 #endif
34 
35 #define USE_STACK_TIMERS
36 
37 namespace qmcplusplus
38 {
39 template<class TIMER>
41 
43 {
44  timer_level_none, // The 'none' settting is not for individual timers.
45  // It is for setting a threshold to turn all timers off.
49  num_timer_levels // this is not a timer level but to count the elements in this enum
50 };
51 
52 extern bool timer_max_level_exceeded;
53 
54 // Unsigned char gives 254 timers (0 is reserved).
55 // Use a longer type (eg. unsigned short) to increase the limit.
56 using timer_id_t = unsigned char;
57 
58 // Key for tracking time per stack. Parametered by size.
59 template<int N>
61 {
62 public:
63  // The union is for a performance hack
64  // Use the array of small types to store the stack of timer id's.
65  // Use the larger types for fast comparison for storage in a map.
66 
67  // If timer_id_t is char, there can be up to 254 timers.
68  // N is the number of long ints to store timer nesting levels.
69  // Each N gives (64 bits/long int) / (8 bits/char) = 8 levels
70  union
71  {
72  long int long_buckets[N];
73  timer_id_t short_buckets[sizeof(long int) * N / sizeof(timer_id_t)];
74  };
75 
76  static const int max_level = sizeof(long int) * N;
77 
79  {
80  for (int j = 0; j < N; j++)
81  {
82  long_buckets[j] = 0;
83  }
84  }
85 
86  int level;
87 
88  void add_id(timer_id_t c1)
89  {
90  short_buckets[level] = c1;
91  if (level >= max_level - 1)
92  {
94  }
95  else
96  {
97  level++;
98  }
99  }
100 
101  void put_id(timer_id_t c1) { short_buckets[level] = c1; }
102 
103  timer_id_t get_id(int idx) const { return short_buckets[idx]; }
104 
105  bool operator==(const StackKeyParam& rhs)
106  {
107  bool same = false;
108  for (int j = 0; j < N; j++)
109  {
110  same &= this->long_buckets[j] == rhs.long_buckets[j];
111  }
112  return same;
113  }
114 
115  bool operator<(const StackKeyParam& rhs) const
116  {
117  for (int j = 0; j < N; j++)
118  {
119  if (!(this->long_buckets[j] == rhs.long_buckets[j]))
120  {
121  return this->long_buckets[j] < rhs.long_buckets[j];
122  }
123  }
124  return this->long_buckets[N - 1] < rhs.long_buckets[N - 1];
125  }
126 };
127 
128 // N = 2 gives 16 nesting levels
130 
131 /** Timer accumulates time and call counts
132  * @tparam CLOCK can be a std::chrono clock or FakeChronoClock
133  */
134 template<class CLOCK>
136 {
137 protected:
138  /// start time of the current measurement
139  typename CLOCK::time_point start_time;
140  /// total time accumulated of all the calls
141  double total_time;
142  /// total call counts
143  long num_calls;
144  /// name of this timer
145  std::string name;
146  /// if false, timer start/stop becomes no-op.
147  bool active;
148  /// timer level
150  /// timer id in registered in the manager
152  /// timer manager which allocated this timer object. nullptr if USE_STACK_TIMERS is not used.
154 #ifdef USE_STACK_TIMERS
155  /// stack key of the current measurement
157 
158  /// total time accumulated per stack key
159  std::map<StackKey, double> per_stack_total_time;
160  /// total call counts per stack key
161  std::map<StackKey, long> per_stack_num_calls;
162 #endif
163 
164 #ifdef USE_VTUNE_TASKS
165  __itt_string_handle* task_name;
166 #endif
167 public:
168  void start();
169  void stop();
170 
171 #ifdef USE_STACK_TIMERS
172  std::map<StackKey, double>& get_per_stack_total_time() { return per_stack_total_time; }
173 
175 #endif
176 
177 
178  inline double get_total() const { return total_time; }
179  inline long get_num_calls() const { return num_calls; }
180 
181 #ifdef USE_STACK_TIMERS
182  inline double get_total(const StackKey& key) { return per_stack_total_time[key]; }
183  inline long get_num_calls(const StackKey& key) { return per_stack_num_calls[key]; }
184 #endif
185 
186  timer_id_t get_id() const { return timer_id; }
187 
188  void set_id(timer_id_t id) { timer_id = id; }
189 
190  inline std::string get_name() const { return name; }
191 
192  inline void reset()
193  {
194  num_calls = 0;
195  total_time = 0.0;
196  }
197 
198  TimerType(const std::string& myname,
199  TimerManager<TimerType<CLOCK>>* mymanager,
200  timer_levels mytimer = timer_level_fine)
201  : total_time(0.0),
202  num_calls(0),
203  name(myname),
204  active(true),
205  timer_level(mytimer),
206  timer_id(0),
207 #ifdef USE_STACK_TIMERS
208  manager(mymanager)
209 #else
210  manager(nullptr)
211 #endif
212  {
213 #ifdef USE_VTUNE_TASKS
214  task_name = __itt_string_handle_create(myname.c_str());
215 #endif
216  }
217 
218  TimerType(const TimerType& o) = delete;
219 
220  void set_name(const std::string& myname) { name = myname; }
221 
222  void set_active(const bool& is_active) { active = is_active; }
223 
224  void set_active_by_timer_threshold(const timer_levels threshold);
225 
226  // Functions for unit testing
227  template<class CLOCK1>
228  friend void set_total_time(TimerType<CLOCK1>* timer, double total_time_input);
229 
230  template<class CLOCK1>
231  friend void set_num_calls(TimerType<CLOCK1>* timer, long num_calls_input);
232 };
233 
236 extern template class TimerType<ChronoClock>;
237 extern template class TimerType<FakeChronoClock>;
238 
239 // Wrapper for timer that starts on construction and stops on destruction
240 template<class TIMER = NewTimer>
242 {
243 public:
244  ScopeGuard(TIMER& t) : timer(t) { timer.start(); }
245 
246  ScopeGuard(const ScopeGuard&) = delete;
247  ScopeGuard& operator=(const ScopeGuard&) = delete;
248  ScopeGuard(ScopeGuard&&) noexcept = default;
249  ScopeGuard& operator=(ScopeGuard&&) noexcept = default;
250 
251  ~ScopeGuard() { timer.stop(); }
252 
253 private:
254  TIMER& timer;
255 };
256 
259 
260 } // namespace qmcplusplus
261 
262 #endif
double get_total(const StackKey &key)
Definition: NewTimer.h:182
std::map< StackKey, double > per_stack_total_time
total time accumulated per stack key
Definition: NewTimer.h:159
long get_num_calls() const
Definition: NewTimer.h:179
timer_id_t get_id(int idx) const
Definition: NewTimer.h:103
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
void set_active_by_timer_threshold(const timer_levels threshold)
Definition: NewTimer.cpp:124
TimerType(const std::string &myname, TimerManager< TimerType< CLOCK >> *mymanager, timer_levels mytimer=timer_level_fine)
Definition: NewTimer.h:198
timer_id_t timer_id
timer id in registered in the manager
Definition: NewTimer.h:151
long num_calls
total call counts
Definition: NewTimer.h:143
friend void set_total_time(TimerType< CLOCK1 > *timer, double total_time_input)
std::string get_name() const
Definition: NewTimer.h:190
Timer accumulates time and call counts.
Definition: NewTimer.h:135
StackKey & get_stack_key()
Definition: NewTimer.h:174
Manager creates timers and handle reports.
Definition: NewTimer.h:40
std::map< StackKey, double > & get_per_stack_total_time()
Definition: NewTimer.h:172
bool operator==(const StackKeyParam &rhs)
Definition: NewTimer.h:105
TimerManager< TimerType< CLOCK > > * manager
timer manager which allocated this timer object. nullptr if USE_STACK_TIMERS is not used...
Definition: NewTimer.h:153
unsigned char timer_id_t
Definition: NewTimer.h:56
CLOCK::time_point start_time
start time of the current measurement
Definition: NewTimer.h:139
void add_id(timer_id_t c1)
Definition: NewTimer.h:88
friend void set_num_calls(TimerType< CLOCK1 > *timer, long num_calls_input)
StackKey current_stack_key
stack key of the current measurement
Definition: NewTimer.h:156
long get_num_calls(const StackKey &key)
Definition: NewTimer.h:183
std::map< StackKey, long > per_stack_num_calls
total call counts per stack key
Definition: NewTimer.h:161
bool active
if false, timer start/stop becomes no-op.
Definition: NewTimer.h:147
void set_id(timer_id_t id)
Definition: NewTimer.h:188
void put_id(timer_id_t c1)
Definition: NewTimer.h:101
bool timer_max_level_exceeded
Definition: NewTimer.cpp:26
double total_time
total time accumulated of all the calls
Definition: NewTimer.h:141
timer_id_t get_id() const
Definition: NewTimer.h:186
void set_active(const bool &is_active)
Definition: NewTimer.h:222
bool operator<(const StackKeyParam &rhs) const
Definition: NewTimer.h:115
std::string name
name of this timer
Definition: NewTimer.h:145
double get_total() const
Definition: NewTimer.h:178
static const int max_level
Definition: NewTimer.h:76
#define USE_STACK_TIMERS
Definition: NewTimer.h:35
timer_levels timer_level
timer level
Definition: NewTimer.h:149
void set_name(const std::string &myname)
Definition: NewTimer.h:220