QMCPACK
TimerManager< TIMER > Class Template Reference

Manager creates timers and handle reports. More...

+ Inheritance diagram for TimerManager< TIMER >:
+ Collaboration diagram for TimerManager< TIMER >:

Classes

struct  FlatProfileData
 
struct  StackProfileData
 

Public Types

using nameList_t = std::map< std::string, int >
 
using timeList_t = std::vector< double >
 
using callList_t = std::vector< long >
 
using names_t = std::vector< std::string >
 

Public Member Functions

 TimerManager ()
 
TIMER * createTimer (const std::string &myname, timer_levels mytimer=timer_level_fine)
 Create a new timer object registred in this manager. This call is thread-safe. More...
 
void push_timer (TIMER *t)
 
void pop_timer (TIMER *t)
 
TIMER * current_timer ()
 
void set_timer_threshold (const timer_levels threshold)
 
void set_timer_threshold (const std::string &threshold)
 
std::string get_timer_threshold_string () const
 
bool maximum_number_of_timers_exceeded () const
 
void reset ()
 
void print (Communicate *comm)
 
void collate_flat_profile (Communicate *comm, FlatProfileData &p)
 
void collate_stack_profile (Communicate *comm, StackProfileData &p)
 
void output_timing (Communicate *comm, Libxml2Document &doc, xmlNodePtr root)
 
void get_stack_name_from_id (const StackKey &key, std::string &name)
 

Private Member Functions

void initializeTimer (TIMER &t)
 
void print_flat (Communicate *comm)
 
void print_stack (Communicate *comm)
 

Private Attributes

std::vector< std::unique_ptr< TIMER > > timer_storage_
 All the timers created by this manager. More...
 
std::mutex timer_list_lock_
 mutex for TimerList More...
 
std::vector< TIMER * > CurrentTimerStack
 The stack of nested active timers. More...
 
timer_levels timer_threshold
 The threshold for active timers. More...
 
timer_id_t max_timer_id
 The current maximal timer id. More...
 
bool max_timers_exceeded
 status of maxmal timer id reached More...
 
std::map< timer_id_t, std::string > timer_id_name
 timer id to name mapping More...
 
std::map< std::string, timer_id_ttimer_name_to_id
 name to timer id mapping More...
 

Detailed Description

template<class TIMER>
class qmcplusplus::TimerManager< TIMER >

Manager creates timers and handle reports.

Template Parameters
TIMERregular or fake timer

TimerManager is generally not thread-safe. Thread-safe functions are noted below.

Definition at line 40 of file NewTimer.h.


Class Documentation

◆ qmcplusplus::TimerManager::FlatProfileData

struct qmcplusplus::TimerManager::FlatProfileData

template<class TIMER>
struct qmcplusplus::TimerManager< TIMER >::FlatProfileData

Definition at line 113 of file TimerManager.h.

+ Collaboration diagram for TimerManager< TIMER >::FlatProfileData:
Class Members
callList_t callList
nameList_t nameList
timeList_t timeList

◆ qmcplusplus::TimerManager::StackProfileData

struct qmcplusplus::TimerManager::StackProfileData

template<class TIMER>
struct qmcplusplus::TimerManager< TIMER >::StackProfileData

Definition at line 120 of file TimerManager.h.

+ Collaboration diagram for TimerManager< TIMER >::StackProfileData:
Class Members
callList_t callList
nameList_t nameList
names_t names
timeList_t timeExclList
timeList_t timeList

Member Typedef Documentation

◆ callList_t

using callList_t = std::vector<long>

Definition at line 110 of file TimerManager.h.

◆ nameList_t

using nameList_t = std::map<std::string, int>

Definition at line 108 of file TimerManager.h.

◆ names_t

using names_t = std::vector<std::string>

Definition at line 111 of file TimerManager.h.

◆ timeList_t

using timeList_t = std::vector<double>

Definition at line 109 of file TimerManager.h.

Constructor & Destructor Documentation

◆ TimerManager()

TimerManager ( )
inline

Definition at line 76 of file TimerManager.h.

77  {
78 #ifdef USE_VTUNE_TASKS
79  task_domain = __itt_domain_create("QMCPACK");
80 #endif
81  }
timer_levels timer_threshold
The threshold for active timers.
Definition: TimerManager.h:56
bool max_timers_exceeded
status of maxmal timer id reached
Definition: TimerManager.h:60
timer_id_t max_timer_id
The current maximal timer id.
Definition: TimerManager.h:58

Member Function Documentation

◆ collate_flat_profile()

void collate_flat_profile ( Communicate comm,
FlatProfileData p 
)

Definition at line 168 of file TimerManager.cpp.

Referenced by qmcplusplus::TEST_CASE().

169 {
170  for (int i = 0; i < timer_storage_.size(); ++i)
171  {
172  TIMER& timer = *timer_storage_[i];
173  nameList_t::iterator it(p.nameList.find(timer.get_name()));
174  if (it == p.nameList.end())
175  {
176  int ind = p.nameList.size();
177  p.nameList[timer.get_name()] = ind;
178  p.timeList.push_back(timer.get_total());
179  p.callList.push_back(timer.get_num_calls());
180  }
181  else
182  {
183  int ind = (*it).second;
184  p.timeList[ind] += timer.get_total();
185  p.callList[ind] += timer.get_num_calls();
186  }
187  }
188 
189  if (comm)
190  {
191  comm->allreduce(p.timeList);
192  comm->allreduce(p.callList);
193  }
194 }
void allreduce(T &)
std::vector< std::unique_ptr< TIMER > > timer_storage_
All the timers created by this manager.
Definition: TimerManager.h:50

◆ collate_stack_profile()

void collate_stack_profile ( Communicate comm,
StackProfileData p 
)

Definition at line 244 of file TimerManager.cpp.

Referenced by qmcplusplus::TEST_CASE().

245 {
246 #ifdef USE_STACK_TIMERS
247  // Put stacks from all timers into one data structure
248  // By naming the timer stacks as 'timer1/timer2', etc, the ordering done by the
249  // map's keys will also place the stacks in depth-first order.
250  // The order in which sibling timers are encountered in the code is not
251  // preserved. They will be ordered alphabetically instead.
252  std::map<std::string, ProfileData> all_stacks;
253  for (int i = 0; i < timer_storage_.size(); ++i)
254  {
255  TIMER& timer = *timer_storage_[i];
256  for (const auto& [key, time] : timer.get_per_stack_total_time())
257  {
258  ProfileData pd;
259  std::string stack_name;
260  get_stack_name_from_id(key, stack_name);
261  pd.time = timer.get_total(key);
262  pd.calls = timer.get_num_calls(key);
263 
264  all_stacks[stack_name] += pd;
265  }
266  }
267 
268  // Fill in the output data structure (but don't compute exclusive time yet)
269  int idx = 0;
270  for (const auto& [stack_name, data] : all_stacks)
271  {
272  p.nameList[stack_name] = idx;
273  p.names.push_back(stack_name);
274  p.timeList.push_back(data.time);
275  p.timeExclList.push_back(data.time);
276  p.callList.push_back(data.calls);
277  idx++;
278  }
279 
280  // Subtract times of immediate children to get exclusive time
281  for (idx = 0; idx < p.timeList.size(); idx++)
282  {
283  int start_level = get_level(p.names[idx]);
284  for (int i = idx + 1; i < p.timeList.size(); i++)
285  {
286  int level = get_level(p.names[i]);
287  if (level == start_level + 1)
288  p.timeExclList[idx] -= p.timeExclList[i];
289 
290  if (level == start_level)
291  break;
292  }
293  }
294 #endif
295 }
int get_level(const std::string &stack_name)
std::vector< std::unique_ptr< TIMER > > timer_storage_
All the timers created by this manager.
Definition: TimerManager.h:50
void get_stack_name_from_id(const StackKey &key, std::string &name)

◆ createTimer()

TIMER * createTimer ( const std::string &  myname,
timer_levels  mytimer = timer_level_fine 
)

Create a new timer object registred in this manager. This call is thread-safe.

Definition at line 84 of file TimerManager.cpp.

Referenced by qmcplusplus::TEST_CASE().

85 {
86  TIMER* t = nullptr;
87  {
88  const std::lock_guard<std::mutex> lock(timer_list_lock_);
89  timer_storage_.push_back(std::make_unique<TIMER>(myname, this, mytimer));
90  t = timer_storage_.back().get();
91  initializeTimer(*t);
92  }
93  return t;
94 }
void initializeTimer(TIMER &t)
std::vector< std::unique_ptr< TIMER > > timer_storage_
All the timers created by this manager.
Definition: TimerManager.h:50
std::mutex timer_list_lock_
mutex for TimerList
Definition: TimerManager.h:52

◆ current_timer()

TIMER* current_timer ( )
inline

Definition at line 90 of file TimerManager.h.

Referenced by qmcplusplus::TEST_CASE().

91  {
92  TIMER* current = nullptr;
93  if (CurrentTimerStack.size() > 0)
94  current = CurrentTimerStack.back();
95 
96  return current;
97  }
std::vector< TIMER * > CurrentTimerStack
The stack of nested active timers.
Definition: TimerManager.h:54

◆ get_stack_name_from_id()

void get_stack_name_from_id ( const StackKey key,
std::string &  name 
)

Definition at line 229 of file TimerManager.cpp.

230 {
231  for (int i = 0; i < StackKey::max_level; i++)
232  {
233  std::string& timer_name = timer_id_name[key.get_id(i)];
234  if (key.get_id(i) == 0)
235  break;
236  if (i > 0)
237  stack_name += TIMER_STACK_SEPARATOR;
238 
239  stack_name += timer_name;
240  }
241 }
std::map< timer_id_t, std::string > timer_id_name
timer id to name mapping
Definition: TimerManager.h:62
static const int max_level
Definition: NewTimer.h:76

◆ get_timer_threshold_string()

std::string get_timer_threshold_string ( ) const

Definition at line 161 of file TimerManager.cpp.

162 {
163  return timer_level_names[timer_threshold];
164 }
timer_levels timer_threshold
The threshold for active timers.
Definition: TimerManager.h:56

◆ initializeTimer()

void initializeTimer ( TIMER &  t)
private

Definition at line 57 of file TimerManager.cpp.

58 {
59  if (t.get_name().find(TIMER_STACK_SEPARATOR) != std::string::npos)
60  app_log() << "Warning: Timer name (" << t.get_name() << ") should not contain the character "
61  << TIMER_STACK_SEPARATOR << std::endl;
62 
63  if (timer_name_to_id.find(t.get_name()) == timer_name_to_id.end())
64  {
65  t.set_id(max_timer_id);
66  timer_id_name[t.get_id()] = t.get_name();
67  timer_name_to_id[t.get_name()] = t.get_id();
68  if (max_timer_id >= std::numeric_limits<timer_id_t>::max())
69  {
70  max_timers_exceeded = true;
71  app_log() << "Number of timers exceeds limit (" << static_cast<int>(std::numeric_limits<timer_id_t>::max())
72  << "). Adjust timer_id_t in NewTimer.h and recompile." << std::endl;
73  }
74  else
75  max_timer_id++;
76  }
77  else
78  t.set_id(timer_name_to_id[t.get_name()]);
79 
80  t.set_active_by_timer_threshold(timer_threshold);
81 }
std::map< timer_id_t, std::string > timer_id_name
timer id to name mapping
Definition: TimerManager.h:62
std::ostream & app_log()
Definition: OutputManager.h:65
timer_levels timer_threshold
The threshold for active timers.
Definition: TimerManager.h:56
bool max_timers_exceeded
status of maxmal timer id reached
Definition: TimerManager.h:60
timer_id_t max_timer_id
The current maximal timer id.
Definition: TimerManager.h:58
std::map< std::string, timer_id_t > timer_name_to_id
name to timer id mapping
Definition: TimerManager.h:64

◆ maximum_number_of_timers_exceeded()

bool maximum_number_of_timers_exceeded ( ) const
inline

Definition at line 103 of file TimerManager.h.

103 { return max_timers_exceeded; }
bool max_timers_exceeded
status of maxmal timer id reached
Definition: TimerManager.h:60

◆ output_timing()

void output_timing ( Communicate comm,
Libxml2Document doc,
xmlNodePtr  root 
)

Definition at line 419 of file TimerManager.cpp.

Referenced by qmcplusplus::TEST_CASE().

420 {
421 #if defined(ENABLE_TIMERS) && defined(USE_STACK_TIMERS)
422  StackProfileData p;
423 
425 
426  if (comm == nullptr || comm->rank() == 0)
427  {
428  xmlNodePtr timing_root = doc.addChild(root, "timing");
429  doc.addChild(timing_root, "max_stack_level_exceeded", timer_max_level_exceeded ? "yes" : "no");
430  doc.addChild(timing_root, "max_timers_exceeded", max_timers_exceeded ? "yes" : "no");
431  std::vector<xmlNodePtr> node_stack;
432  node_stack.push_back(timing_root);
433  xmlNodePtr current_root = timing_root;
434 
435  for (int i = 0; i < p.names.size(); i++)
436  {
437  std::string stack_name = p.names[i];
438  int level = get_level(stack_name);
439  std::string name = get_leaf_name(stack_name);
440 
441  std::string indent_str(2 * level, ' ');
442 
443  xmlNodePtr timer = doc.addChild(current_root, "timer");
444  doc.addChild(timer, "name", name);
445  doc.addChild(timer, "time_incl", p.timeList[i]);
446  doc.addChild(timer, "time_excl", p.timeExclList[i]);
447  doc.addChild(timer, "calls", p.callList[i]);
448 
449  int next_level = level;
450  if (i + 1 < p.names.size())
451  next_level = get_level(p.names[i + 1]);
452 
453  if (next_level > level)
454  {
455  xmlNodePtr next_node = doc.addChild(timer, "includes");
456  node_stack.push_back(next_node);
457  current_root = next_node;
458  }
459  if (next_level < level)
460  for (int j = 0; j < level - next_level; j++)
461  {
462  node_stack.pop_back();
463  current_root = node_stack.back();
464  }
465  }
466  }
467 
468 #endif
469 }
int rank() const
return the rank
Definition: Communicate.h:116
std::string get_leaf_name(const std::string &stack_name)
void collate_stack_profile(Communicate *comm, StackProfileData &p)
bool max_timers_exceeded
status of maxmal timer id reached
Definition: TimerManager.h:60
int get_level(const std::string &stack_name)
bool timer_max_level_exceeded
Definition: NewTimer.cpp:26
void addChild(xmlNodePtr newnode)
Definition: Libxml2Doc.cpp:111

◆ pop_timer()

void pop_timer ( TIMER *  t)

Definition at line 113 of file TimerManager.cpp.

114 {
115  TIMER* stack_top = current_timer();
116  if (stack_top == nullptr)
117  {
118  std::cerr << "Timer stack pop failed on an empty stack! Requested \"" << t->get_name() << "\"." << std::endl;
119  throw std::runtime_error("TimerManager pop_timer error!");
120  }
121  else if (t != stack_top)
122  {
123  std::cerr << "Timer stack pop not matching push! "
124  << "Expecting \"" << t->get_name() << "\" but \"" << stack_top->get_name() << "\" is on the top."
125  << std::endl;
126  throw std::runtime_error("TimerManager pop_timer error!");
127  }
128  else
129  CurrentTimerStack.pop_back();
130 }
std::vector< TIMER * > CurrentTimerStack
The stack of nested active timers.
Definition: TimerManager.h:54

◆ print()

void print ( Communicate comm)

Definition at line 298 of file TimerManager.cpp.

299 {
301  return;
302 #ifdef ENABLE_TIMERS
303  app_log() << std::endl;
304  app_log() << "Use --enable-timers=<value> command line option to increase or decrease level of timing information"
305  << std::endl;
306 #ifdef USE_STACK_TIMERS
307  if (comm == nullptr || comm->rank() == 0)
308  app_log() << "Stack timer profile" << std::endl;
309  print_stack(comm);
310 #else
311  if (comm == nullptr || comm->rank() == 0)
312  app_log() << "\nFlat profile" << std::endl;
313  print_flat(comm);
314 #endif
315 #endif
316 }
int rank() const
return the rank
Definition: Communicate.h:116
std::ostream & app_log()
Definition: OutputManager.h:65
timer_levels timer_threshold
The threshold for active timers.
Definition: TimerManager.h:56
void print_flat(Communicate *comm)
void print_stack(Communicate *comm)

◆ print_flat()

void print_flat ( Communicate comm)
private

Definition at line 319 of file TimerManager.cpp.

320 {
321 #ifdef ENABLE_TIMERS
322  FlatProfileData p;
323 
325 
326  if (comm == nullptr || comm->rank() == 0)
327  {
328 #pragma omp master
329  {
330  std::array<char, 256> tmpout;
331  std::map<std::string, int>::iterator it(p.nameList.begin()), it_end(p.nameList.end());
332  while (it != it_end)
333  {
334  int i = (*it).second;
335  int length =
336  std::snprintf(tmpout.data(), tmpout.size(), "%-40s %9.4f %13ld %16.9f %12.6f TIMER\n",
337  (*it).first.c_str(), p.timeList[i], p.callList[i],
338  p.timeList[i] / (static_cast<double>(p.callList[i]) + std::numeric_limits<double>::epsilon()),
339  p.timeList[i] / static_cast<double>(omp_get_max_threads() * comm->size()));
340  if (length < 0)
341  throw std::runtime_error("Error generating timer string");
342  app_log() << std::string_view(tmpout.data(), length);
343  ++it;
344  }
345  }
346  }
347 #endif
348 }
int rank() const
return the rank
Definition: Communicate.h:116
std::ostream & app_log()
Definition: OutputManager.h:65
int size() const
return the number of tasks
Definition: Communicate.h:118
omp_int_t omp_get_max_threads()
Definition: OpenMP.h:26
void collate_flat_profile(Communicate *comm, FlatProfileData &p)

◆ print_stack()

void print_stack ( Communicate comm)
private

Definition at line 360 of file TimerManager.cpp.

361 {
362 #ifdef ENABLE_TIMERS
363  StackProfileData p;
364 
366 
367  if (comm == nullptr || comm->rank() == 0)
368  {
370  {
371  app_warning() << "Maximum stack level (" << StackKey::max_level << ") exceeded. Results may be incorrect."
372  << std::endl;
373  app_warning() << "Adjust StackKey in NewTimer.h and recompile." << std::endl;
374  }
375 
376  int indent_len = 2;
377  int max_name_len = 0;
378  for (int i = 0; i < p.names.size(); i++)
379  {
380  std::string stack_name = p.names[i];
381  int level = get_level(stack_name);
382  std::string name = get_leaf_name(stack_name);
383  int name_len = name.size() + indent_len * level;
384  max_name_len = std::max(name_len, max_name_len);
385  }
386 
387  std::array<char, 256> tmpout;
388  std::string timer_name;
389  pad_string("Timer", timer_name, max_name_len);
390 
391  int length = std::snprintf(tmpout.data(), tmpout.size(), "%s %-9s %-9s %-10s %-13s\n", timer_name.c_str(),
392  "Inclusive_time", "Exclusive_time", "Calls", "Time_per_call");
393  if (length < 0)
394  throw std::runtime_error("Error generating timer string");
395  app_log() << std::string_view(tmpout.data(), length);
396 
397  for (int i = 0; i < p.names.size(); i++)
398  {
399  std::string stack_name = p.names[i];
400  int level = get_level(stack_name);
401  std::string name = get_leaf_name(stack_name);
402  std::string indent_str(indent_len * level, ' ');
403  std::string indented_str = indent_str + name;
404  std::string padded_name_str;
405  pad_string(indented_str, padded_name_str, max_name_len);
406  length =
407  std::snprintf(tmpout.data(), tmpout.size(), "%s %9.4f %9.4f %13ld %16.9f\n", padded_name_str.c_str(),
408  p.timeList[i], p.timeExclList[i], p.callList[i],
409  p.timeList[i] / (static_cast<double>(p.callList[i]) + std::numeric_limits<double>::epsilon()));
410  if (length < 0)
411  throw std::runtime_error("Error generating timer string");
412  app_log() << std::string_view(tmpout.data(), length);
413  }
414  }
415 #endif
416 }
std::ostream & app_warning()
Definition: OutputManager.h:69
int rank() const
return the rank
Definition: Communicate.h:116
std::string get_leaf_name(const std::string &stack_name)
void collate_stack_profile(Communicate *comm, StackProfileData &p)
std::ostream & app_log()
Definition: OutputManager.h:65
int get_level(const std::string &stack_name)
bool timer_max_level_exceeded
Definition: NewTimer.cpp:26
void pad_string(const std::string &in, std::string &out, int field_len)
static const int max_level
Definition: NewTimer.h:76

◆ push_timer()

void push_timer ( TIMER *  t)

Definition at line 97 of file TimerManager.cpp.

98 {
99  // current_timer() can be nullptr when the stack was empty.
100  if (t == current_timer())
101  {
102  std::cerr << "Timer " << t->get_name()
103  << " instance is already at the top of the stack. "
104  "start() is being called again. This often happens when stop() is not paired properly with start(). "
105  << "ScopedTimer uses RAII and manages timer start/stop more safely." << std::endl;
106  throw std::runtime_error("TimerManager push_timer error!");
107  }
108  else
109  CurrentTimerStack.push_back(t);
110 }
std::vector< TIMER * > CurrentTimerStack
The stack of nested active timers.
Definition: TimerManager.h:54

◆ reset()

void reset ( )

Definition at line 133 of file TimerManager.cpp.

134 {
135  for (int i = 0; i < timer_storage_.size(); i++)
136  timer_storage_[i]->reset();
137 }
std::vector< std::unique_ptr< TIMER > > timer_storage_
All the timers created by this manager.
Definition: TimerManager.h:50

◆ set_timer_threshold() [1/2]

void set_timer_threshold ( const timer_levels  threshold)

Definition at line 140 of file TimerManager.cpp.

Referenced by qmcplusplus::TEST_CASE().

141 {
142  timer_threshold = threshold;
143  for (int i = 0; i < timer_storage_.size(); i++)
144  timer_storage_[i]->set_active_by_timer_threshold(timer_threshold);
145 }
timer_levels timer_threshold
The threshold for active timers.
Definition: TimerManager.h:56
std::vector< std::unique_ptr< TIMER > > timer_storage_
All the timers created by this manager.
Definition: TimerManager.h:50

◆ set_timer_threshold() [2/2]

void set_timer_threshold ( const std::string &  threshold)

Definition at line 148 of file TimerManager.cpp.

149 {
150  const auto it = std::find(timer_level_names.begin(), timer_level_names.end(), threshold);
151  if (it != timer_level_names.end())
152  set_timer_threshold(static_cast<timer_levels>(std::distance(timer_level_names.begin(), it)));
153  else
154  {
155  std::cerr << "Unknown timer level: " << threshold << " , current level: " << timer_level_names[timer_threshold]
156  << std::endl;
157  }
158 }
timer_levels timer_threshold
The threshold for active timers.
Definition: TimerManager.h:56
void set_timer_threshold(const timer_levels threshold)

Member Data Documentation

◆ CurrentTimerStack

std::vector<TIMER*> CurrentTimerStack
private

The stack of nested active timers.

Definition at line 54 of file TimerManager.h.

Referenced by TimerManager< qmcplusplus::TimerType< CLOCK > >::current_timer().

◆ max_timer_id

timer_id_t max_timer_id
private

The current maximal timer id.

Definition at line 58 of file TimerManager.h.

◆ max_timers_exceeded

bool max_timers_exceeded
private

status of maxmal timer id reached

Definition at line 60 of file TimerManager.h.

Referenced by TimerManager< qmcplusplus::TimerType< CLOCK > >::maximum_number_of_timers_exceeded().

◆ timer_id_name

std::map<timer_id_t, std::string> timer_id_name
private

timer id to name mapping

Definition at line 62 of file TimerManager.h.

◆ timer_list_lock_

std::mutex timer_list_lock_
private

mutex for TimerList

Definition at line 52 of file TimerManager.h.

◆ timer_name_to_id

std::map<std::string, timer_id_t> timer_name_to_id
private

name to timer id mapping

Definition at line 64 of file TimerManager.h.

◆ timer_storage_

std::vector<std::unique_ptr<TIMER> > timer_storage_
private

All the timers created by this manager.

Definition at line 50 of file TimerManager.h.

◆ timer_threshold

timer_levels timer_threshold
private

The threshold for active timers.

Definition at line 56 of file TimerManager.h.


The documentation for this class was generated from the following files: