Intel® OpenMP* Runtime Library
 All Classes Functions Variables Typedefs Enumerations Enumerator Groups Pages
kmp_stats.h
1 #ifndef KMP_STATS_H
2 #define KMP_STATS_H
3 
8 /* <copyright>
9  Copyright (c) 1997-2015 Intel Corporation. All Rights Reserved.
10 
11  Redistribution and use in source and binary forms, with or without
12  modification, are permitted provided that the following conditions
13  are met:
14 
15  * Redistributions of source code must retain the above copyright
16  notice, this list of conditions and the following disclaimer.
17  * Redistributions in binary form must reproduce the above copyright
18  notice, this list of conditions and the following disclaimer in the
19  documentation and/or other materials provided with the distribution.
20  * Neither the name of Intel Corporation nor the names of its
21  contributors may be used to endorse or promote products derived
22  from this software without specific prior written permission.
23 
24  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28  HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 
36 </copyright> */
37 
38 #if KMP_STATS_ENABLED
39 /*
40  * Statistics accumulator.
41  * Accumulates number of samples and computes min, max, mean, standard deviation on the fly.
42  *
43  * Online variance calculation algorithm from http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#On-line_algorithm
44  */
45 
46 #include <limits>
47 #include <math.h>
48 #include <string>
49 #include <stdint.h>
50 #include <new> // placement new
51 #include "kmp_stats_timing.h"
52 
53 
60  public:
61  const static int onlyInMaster = 1<<0;
62  const static int noUnits = 1<<1;
63  const static int synthesized = 1<<2;
64  const static int notInMaster = 1<<3;
65  const static int logEvent = 1<<4;
66 };
67 
84 #define KMP_FOREACH_COUNTER(macro, arg) \
85  macro (OMP_PARALLEL, stats_flags_e::onlyInMaster, arg) \
86  macro (OMP_FOR_static, 0, arg) \
87  macro (OMP_FOR_dynamic, 0, arg) \
88  macro (OMP_DISTR_FOR_static, 0, arg) \
89  macro (OMP_DISTR_FOR_dynamic, 0, arg) \
90  macro (OMP_BARRIER, 0, arg) \
91  macro (OMP_CRITICAL,0, arg) \
92  macro (OMP_SINGLE, 0, arg) \
93  macro (OMP_MASTER, 0, arg) \
94  macro (OMP_set_lock, 0, arg) \
95  macro (OMP_test_lock, 0, arg) \
96  macro (OMP_test_lock_failure, 0, arg) \
97  macro (REDUCE_wait, 0, arg) \
98  macro (REDUCE_nowait, 0, arg) \
99  macro (LAST,0,arg)
100 
115 #define KMP_FOREACH_TIMER(macro, arg) \
116  macro (OMP_PARALLEL_args, stats_flags_e::onlyInMaster | stats_flags_e::noUnits, arg) \
117  macro (FOR_static_iterations, stats_flags_e::onlyInMaster | stats_flags_e::noUnits, arg) \
118  macro (FOR_dynamic_iterations, stats_flags_e::noUnits, arg) \
119  macro (OMP_start_end, stats_flags_e::onlyInMaster, arg) \
120  macro (OMP_serial, stats_flags_e::onlyInMaster, arg) \
121  macro (OMP_work, 0, arg) \
122  macro (Total_work, stats_flags_e::synthesized, arg) \
123  macro (OMP_await_work, stats_flags_e::notInMaster, arg) \
124  macro (Total_await_work, stats_flags_e::synthesized, arg) \
125  macro (OMP_barrier, 0, arg) \
126  macro (Total_barrier, stats_flags_e::synthesized, arg) \
127  macro (OMP_test_lock, 0, arg) \
128  macro (FOR_static_scheduling, 0, arg) \
129  macro (FOR_dynamic_scheduling, 0, arg) \
130  macro (KMP_fork_call, 0, arg) \
131  macro (KMP_join_call, 0, arg) \
132  macro (KMP_fork_barrier, stats_flags_e::logEvent, arg) \
133  macro (KMP_join_barrier, stats_flags_e::logEvent, arg) \
134  macro (KMP_barrier, 0, arg) \
135  macro (KMP_end_split_barrier, 0, arg) \
136  macro (KMP_wait_sleep, 0, arg) \
137  macro (KMP_release, 0, arg) \
138  macro (KMP_hier_gather, 0, arg) \
139  macro (KMP_hier_release, 0, arg) \
140  macro (KMP_hyper_gather, stats_flags_e::logEvent, arg) \
141  macro (KMP_hyper_release, stats_flags_e::logEvent, arg) \
142  macro (KMP_linear_gather, 0, arg) \
143  macro (KMP_linear_release, 0, arg) \
144  macro (KMP_tree_gather, 0, arg) \
145  macro (KMP_tree_release, 0, arg) \
146  macro (USER_master_invoke, stats_flags_e::logEvent, arg) \
147  macro (USER_worker_invoke, stats_flags_e::logEvent, arg) \
148  macro (USER_resume, stats_flags_e::logEvent, arg) \
149  macro (USER_suspend, stats_flags_e::logEvent, arg) \
150  macro (USER_launch_thread_loop, stats_flags_e::logEvent, arg) \
151  macro (KMP_allocate_team, 0, arg) \
152  macro (KMP_setup_icv_copy, 0, arg) \
153  macro (USER_icv_copy, 0, arg) \
154  macro (LAST,0, arg)
155 
156 
157 
158 // OMP_PARALLEL_args -- the number of arguments passed to a fork
159 // FOR_static_iterations -- Number of available parallel chunks of work in a static for
160 // FOR_dynamic_iterations -- Number of available parallel chunks of work in a dynamic for
161 // Both adjust for any chunking, so if there were an iteration count of 20 but a chunk size of 10, we'd record 2.
162 // OMP_serial -- thread zero time executing serial code
163 // OMP_start_end -- time from when OpenMP is initialized until the stats are printed at exit
164 // OMP_work -- elapsed time in code dispatched by a fork (measured in the thread)
165 // Total_work -- a synthesized statistic summarizing how much parallel work each thread executed.
166 // OMP_barrier -- time at "real" barriers
167 // Total_barrier -- a synthesized statistic summarizing how much time at real barriers in each thread
168 // OMP_set_lock -- time in lock setting
169 // OMP_test_lock -- time in testing a lock
170 // LOCK_WAIT -- time waiting for a lock
171 // FOR_static_scheduling -- time spent doing scheduling for a static "for"
172 // FOR_dynamic_scheduling -- time spent doing scheduling for a dynamic "for"
173 // KMP_wait_sleep -- time in __kmp_wait_sleep
174 // KMP_release -- time in __kmp_release
175 // KMP_fork_barrier -- time in __kmp_fork_barrier
176 // KMP_join_barrier -- time in __kmp_join_barrier
177 // KMP_barrier -- time in __kmp_barrier
178 // KMP_end_split_barrier -- time in __kmp_end_split_barrier
179 // KMP_setup_icv_copy -- time in __kmp_setup_icv_copy
180 // KMP_icv_copy -- start/stop timer for any ICV copying
181 // KMP_linear_gather -- time in __kmp_linear_barrier_gather
182 // KMP_linear_release -- time in __kmp_linear_barrier_release
183 // KMP_tree_gather -- time in __kmp_tree_barrier_gather
184 // KMP_tree_release -- time in __kmp_tree_barrier_release
185 // KMP_hyper_gather -- time in __kmp_hyper_barrier_gather
186 // KMP_hyper_release -- time in __kmp_hyper_barrier_release
187 
204 #define KMP_FOREACH_EXPLICIT_TIMER(macro, arg) \
205  macro(OMP_serial, 0, arg) \
206  macro(OMP_start_end, 0, arg) \
207  macro(USER_icv_copy, 0, arg) \
208  macro(USER_launch_thread_loop, stats_flags_e::logEvent, arg) \
209  macro(LAST, 0, arg)
210 
211 #define ENUMERATE(name,ignore,prefix) prefix##name,
212 enum timer_e {
213  KMP_FOREACH_TIMER(ENUMERATE, TIMER_)
214 };
215 
216 enum explicit_timer_e {
217  KMP_FOREACH_EXPLICIT_TIMER(ENUMERATE, EXPLICIT_TIMER_)
218 };
219 
220 enum counter_e {
221  KMP_FOREACH_COUNTER(ENUMERATE, COUNTER_)
222 };
223 #undef ENUMERATE
224 
225 class statistic
226 {
227  double minVal;
228  double maxVal;
229  double meanVal;
230  double m2;
231  uint64_t sampleCount;
232 
233  public:
234  statistic() { reset(); }
235  statistic (statistic const &o): minVal(o.minVal), maxVal(o.maxVal), meanVal(o.meanVal), m2(o.m2), sampleCount(o.sampleCount) {}
236 
237  double getMin() const { return minVal; }
238  double getMean() const { return meanVal; }
239  double getMax() const { return maxVal; }
240  uint64_t getCount() const { return sampleCount; }
241  double getSD() const { return sqrt(m2/sampleCount); }
242  double getTotal() const { return sampleCount*meanVal; }
243 
244  void reset()
245  {
246  minVal = std::numeric_limits<double>::max();
247  maxVal = -std::numeric_limits<double>::max();
248  meanVal= 0.0;
249  m2 = 0.0;
250  sampleCount = 0;
251  }
252  void addSample(double sample);
253  void scale (double factor);
254  void scaleDown(double f) { scale (1./f); }
255  statistic & operator+= (statistic const & other);
256 
257  std::string format(char unit, bool total=false) const;
258 };
259 
260 struct statInfo
261 {
262  const char * name;
263  uint32_t flags;
264 };
265 
266 class timeStat : public statistic
267 {
268  static statInfo timerInfo[];
269 
270  public:
271  timeStat() : statistic() {}
272  static const char * name(timer_e e) { return timerInfo[e].name; }
273  static bool masterOnly (timer_e e) { return timerInfo[e].flags & stats_flags_e::onlyInMaster; }
274  static bool workerOnly (timer_e e) { return timerInfo[e].flags & stats_flags_e::notInMaster; }
275  static bool noUnits (timer_e e) { return timerInfo[e].flags & stats_flags_e::noUnits; }
276  static bool synthesized(timer_e e) { return timerInfo[e].flags & stats_flags_e::synthesized; }
277  static bool logEvent (timer_e e) { return timerInfo[e].flags & stats_flags_e::logEvent; }
278  static void clearEventFlags() {
279  int i;
280  for(i=0;i<TIMER_LAST;i++) {
281  timerInfo[i].flags &= (~(stats_flags_e::logEvent));
282  }
283  }
284 };
285 
286 // Where we need explicitly to start and end the timer, this version can be used
287 // Since these timers normally aren't nicely scoped, so don't have a good place to live
288 // on the stack of the thread, they're more work to use.
289 class explicitTimer
290 {
291  timeStat * stat;
292  tsc_tick_count startTime;
293 
294  public:
295  explicitTimer () : stat(0), startTime(0) { }
296  explicitTimer (timeStat * s) : stat(s), startTime() { }
297 
298  void setStat (timeStat *s) { stat = s; }
299  void start(timer_e timerEnumValue);
300  void stop(timer_e timerEnumValue);
301  void reset() { startTime = 0; }
302 };
303 
304 // Where all you need is to time a block, this is enough.
305 // (It avoids the need to have an explicit end, leaving the scope suffices.)
306 class blockTimer : public explicitTimer
307 {
308  timer_e timerEnumValue;
309  public:
310  blockTimer (timeStat * s, timer_e newTimerEnumValue) : timerEnumValue(newTimerEnumValue), explicitTimer(s) { start(timerEnumValue); }
311  ~blockTimer() { stop(timerEnumValue); }
312 };
313 
314 // If all you want is a count, then you can use this...
315 // The individual per-thread counts will be aggregated into a statistic at program exit.
316 class counter
317 {
318  uint64_t value;
319  static const statInfo counterInfo[];
320 
321  public:
322  counter() : value(0) {}
323  void increment() { value++; }
324  uint64_t getValue() const { return value; }
325  void reset() { value = 0; }
326  static const char * name(counter_e e) { return counterInfo[e].name; }
327  static bool masterOnly (counter_e e) { return counterInfo[e].flags & stats_flags_e::onlyInMaster; }
328 };
329 
330 /* ****************************************************************
331  Class to implement an event
332 
333  There are four components to an event: start time, stop time
334  nest_level, and timer_name.
335  The start and stop time should be obvious (recorded in clock ticks).
336  The nest_level relates to the bar width in the timeline graph.
337  The timer_name is used to determine which timer event triggered this event.
338 
339  the interface to this class is through four read-only operations:
340  1) getStart() -- returns the start time as 64 bit integer
341  2) getStop() -- returns the stop time as 64 bit integer
342  3) getNestLevel() -- returns the nest level of the event
343  4) getTimerName() -- returns the timer name that triggered event
344 
345  *MORE ON NEST_LEVEL*
346  The nest level is used in the bar graph that represents the timeline.
347  Its main purpose is for showing how events are nested inside eachother.
348  For example, say events, A, B, and C are recorded. If the timeline
349  looks like this:
350 
351 Begin -------------------------------------------------------------> Time
352  | | | | | |
353  A B C C B A
354  start start start end end end
355 
356  Then A, B, C will have a nest level of 1, 2, 3 respectively.
357  These values are then used to calculate the barwidth so you can
358  see that inside A, B has occurred, and inside B, C has occurred.
359  Currently, this is shown with A's bar width being larger than B's
360  bar width, and B's bar width being larger than C's bar width.
361 
362 **************************************************************** */
363 class kmp_stats_event {
364  uint64_t start;
365  uint64_t stop;
366  int nest_level;
367  timer_e timer_name;
368  public:
369  kmp_stats_event() : start(0), stop(0), nest_level(0), timer_name(TIMER_LAST) {}
370  kmp_stats_event(uint64_t strt, uint64_t stp, int nst, timer_e nme) : start(strt), stop(stp), nest_level(nst), timer_name(nme) {}
371  inline uint64_t getStart() const { return start; }
372  inline uint64_t getStop() const { return stop; }
373  inline int getNestLevel() const { return nest_level; }
374  inline timer_e getTimerName() const { return timer_name; }
375 };
376 
377 /* ****************************************************************
378  Class to implement a dynamically expandable array of events
379 
380  ---------------------------------------------------------
381  | event 1 | event 2 | event 3 | event 4 | ... | event N |
382  ---------------------------------------------------------
383 
384  An event is pushed onto the back of this array at every
385  explicitTimer->stop() call. The event records the thread #,
386  start time, stop time, and nest level related to the bar width.
387 
388  The event vector starts at size INIT_SIZE and grows (doubles in size)
389  if needed. An implication of this behavior is that log(N)
390  reallocations are needed (where N is number of events). If you want
391  to avoid reallocations, then set INIT_SIZE to a large value.
392 
393  the interface to this class is through six operations:
394  1) reset() -- sets the internal_size back to 0 but does not deallocate any memory
395  2) size() -- returns the number of valid elements in the vector
396  3) push_back(start, stop, nest, timer_name) -- pushes an event onto
397  the back of the array
398  4) deallocate() -- frees all memory associated with the vector
399  5) sort() -- sorts the vector by start time
400  6) operator[index] or at(index) -- returns event reference at that index
401 
402 **************************************************************** */
403 class kmp_stats_event_vector {
404  kmp_stats_event* events;
405  int internal_size;
406  int allocated_size;
407  static const int INIT_SIZE = 1024;
408  public:
409  kmp_stats_event_vector() {
410  events = (kmp_stats_event*)__kmp_allocate(sizeof(kmp_stats_event)*INIT_SIZE);
411  internal_size = 0;
412  allocated_size = INIT_SIZE;
413  }
414  ~kmp_stats_event_vector() {}
415  inline void reset() { internal_size = 0; }
416  inline int size() const { return internal_size; }
417  void push_back(uint64_t start_time, uint64_t stop_time, int nest_level, timer_e name) {
418  int i;
419  if(internal_size == allocated_size) {
420  kmp_stats_event* tmp = (kmp_stats_event*)__kmp_allocate(sizeof(kmp_stats_event)*allocated_size*2);
421  for(i=0;i<internal_size;i++) tmp[i] = events[i];
422  __kmp_free(events);
423  events = tmp;
424  allocated_size*=2;
425  }
426  events[internal_size] = kmp_stats_event(start_time, stop_time, nest_level, name);
427  internal_size++;
428  return;
429  }
430  void deallocate();
431  void sort();
432  const kmp_stats_event & operator[](int index) const { return events[index]; }
433  kmp_stats_event & operator[](int index) { return events[index]; }
434  const kmp_stats_event & at(int index) const { return events[index]; }
435  kmp_stats_event & at(int index) { return events[index]; }
436 };
437 
438 /* ****************************************************************
439  Class to implement a doubly-linked, circular, statistics list
440 
441  |---| ---> |---| ---> |---| ---> |---| ---> ... next
442  | | | | | | | |
443  |---| <--- |---| <--- |---| <--- |---| <--- ... prev
444  Sentinel first second third
445  Node node node node
446 
447  The Sentinel Node is the user handle on the list.
448  The first node corresponds to thread 0's statistics.
449  The second node corresponds to thread 1's statistics and so on...
450 
451  Each node has a _timers, _counters, and _explicitTimers array to
452  hold that thread's statistics. The _explicitTimers
453  point to the correct _timer and update its statistics at every stop() call.
454  The explicitTimers' pointers are set up in the constructor.
455  Each node also has an event vector to hold that thread's timing events.
456  The event vector expands as necessary and records the start-stop times
457  for each timer.
458 
459  The nestLevel variable is for plotting events and is related
460  to the bar width in the timeline graph.
461 
462  Every thread will have a __thread local pointer to its node in
463  the list. The sentinel node is used by the master thread to
464  store "dummy" statistics before __kmp_create_worker() is called.
465 
466 **************************************************************** */
467 class kmp_stats_list {
468  int gtid;
469  timeStat _timers[TIMER_LAST+1];
470  counter _counters[COUNTER_LAST+1];
471  explicitTimer _explicitTimers[EXPLICIT_TIMER_LAST+1];
472  int _nestLevel; // one per thread
473  kmp_stats_event_vector _event_vector;
474  kmp_stats_list* next;
475  kmp_stats_list* prev;
476  public:
477  kmp_stats_list() : next(this) , prev(this) , _event_vector(), _nestLevel(0) {
478 #define doInit(name,ignore1,ignore2) \
479  getExplicitTimer(EXPLICIT_TIMER_##name)->setStat(getTimer(TIMER_##name));
480  KMP_FOREACH_EXPLICIT_TIMER(doInit,0);
481 #undef doInit
482  }
483  ~kmp_stats_list() { }
484  inline timeStat * getTimer(timer_e idx) { return &_timers[idx]; }
485  inline counter * getCounter(counter_e idx) { return &_counters[idx]; }
486  inline explicitTimer * getExplicitTimer(explicit_timer_e idx) { return &_explicitTimers[idx]; }
487  inline timeStat * getTimers() { return _timers; }
488  inline counter * getCounters() { return _counters; }
489  inline explicitTimer * getExplicitTimers() { return _explicitTimers; }
490  inline kmp_stats_event_vector & getEventVector() { return _event_vector; }
491  inline void resetEventVector() { _event_vector.reset(); }
492  inline void incrementNestValue() { _nestLevel++; }
493  inline int getNestValue() { return _nestLevel; }
494  inline void decrementNestValue() { _nestLevel--; }
495  inline int getGtid() const { return gtid; }
496  inline void setGtid(int newgtid) { gtid = newgtid; }
497  kmp_stats_list* push_back(int gtid); // returns newly created list node
498  inline void push_event(uint64_t start_time, uint64_t stop_time, int nest_level, timer_e name) {
499  _event_vector.push_back(start_time, stop_time, nest_level, name);
500  }
501  void deallocate();
502  class iterator;
503  kmp_stats_list::iterator begin();
504  kmp_stats_list::iterator end();
505  int size();
506  class iterator {
507  kmp_stats_list* ptr;
508  friend kmp_stats_list::iterator kmp_stats_list::begin();
509  friend kmp_stats_list::iterator kmp_stats_list::end();
510  public:
511  iterator();
512  ~iterator();
513  iterator operator++();
514  iterator operator++(int dummy);
515  iterator operator--();
516  iterator operator--(int dummy);
517  bool operator!=(const iterator & rhs);
518  bool operator==(const iterator & rhs);
519  kmp_stats_list* operator*() const; // dereference operator
520  };
521 };
522 
523 /* ****************************************************************
524  Class to encapsulate all output functions and the environment variables
525 
526  This module holds filenames for various outputs (normal stats, events, plot file),
527  as well as coloring information for the plot file.
528 
529  The filenames and flags variables are read from environment variables.
530  These are read once by the constructor of the global variable __kmp_stats_output
531  which calls init().
532 
533  During this init() call, event flags for the timeStat::timerInfo[] global array
534  are cleared if KMP_STATS_EVENTS is not true (on, 1, yes).
535 
536  The only interface function that is public is outputStats(heading). This function
537  should print out everything it needs to, either to files or stderr,
538  depending on the environment variables described below
539 
540  ENVIRONMENT VARIABLES:
541  KMP_STATS_FILE -- if set, all statistics (not events) will be printed to this file,
542  otherwise, print to stderr
543  KMP_STATS_THREADS -- if set to "on", then will print per thread statistics to either
544  KMP_STATS_FILE or stderr
545  KMP_STATS_PLOT_FILE -- if set, print the ploticus plot file to this filename,
546  otherwise, the plot file is sent to "events.plt"
547  KMP_STATS_EVENTS -- if set to "on", then log events, otherwise, don't log events
548  KMP_STATS_EVENTS_FILE -- if set, all events are outputted to this file,
549  otherwise, output is sent to "events.dat"
550 
551 **************************************************************** */
552 class kmp_stats_output_module {
553 
554  public:
555  struct rgb_color {
556  float r;
557  float g;
558  float b;
559  };
560 
561  private:
562  static const char* outputFileName;
563  static const char* eventsFileName;
564  static const char* plotFileName;
565  static int printPerThreadFlag;
566  static int printPerThreadEventsFlag;
567  static const rgb_color globalColorArray[];
568  static rgb_color timerColorInfo[];
569 
570  void init();
571  static void setupEventColors();
572  static void printPloticusFile();
573  static void printStats(FILE *statsOut, statistic const * theStats, bool areTimers);
574  static void printCounters(FILE * statsOut, counter const * theCounters);
575  static void printEvents(FILE * eventsOut, kmp_stats_event_vector* theEvents, int gtid);
576  static rgb_color getEventColor(timer_e e) { return timerColorInfo[e]; }
577  static void windupExplicitTimers();
578  bool eventPrintingEnabled() {
579  if(printPerThreadEventsFlag) return true;
580  else return false;
581  }
582  bool perThreadPrintingEnabled() {
583  if(printPerThreadFlag) return true;
584  else return false;
585  }
586 
587  public:
588  kmp_stats_output_module() { init(); }
589  void outputStats(const char* heading);
590 };
591 
592 #ifdef __cplusplus
593 extern "C" {
594 #endif
595 void __kmp_stats_init();
596 void __kmp_reset_stats();
597 void __kmp_output_stats(const char *);
598 void __kmp_accumulate_stats_at_exit(void);
599 // thread local pointer to stats node within list
600 extern __thread kmp_stats_list* __kmp_stats_thread_ptr;
601 // head to stats list.
602 extern kmp_stats_list __kmp_stats_list;
603 // lock for __kmp_stats_list
604 extern kmp_tas_lock_t __kmp_stats_lock;
605 // reference start time
606 extern tsc_tick_count __kmp_stats_start_time;
607 // interface to output
608 extern kmp_stats_output_module __kmp_stats_output;
609 
610 #ifdef __cplusplus
611 }
612 #endif
613 
614 // Simple, standard interfaces that drop out completely if stats aren't enabled
615 
616 
629 #define KMP_TIME_BLOCK(name) \
630  blockTimer __BLOCKTIME__(__kmp_stats_thread_ptr->getTimer(TIMER_##name), TIMER_##name)
631 
642 #define KMP_COUNT_VALUE(name, value) \
643  __kmp_stats_thread_ptr->getTimer(TIMER_##name)->addSample(value)
644 
654 #define KMP_COUNT_BLOCK(name) \
655  __kmp_stats_thread_ptr->getCounter(COUNTER_##name)->increment()
656 
668 #define KMP_START_EXPLICIT_TIMER(name) \
669  __kmp_stats_thread_ptr->getExplicitTimer(EXPLICIT_TIMER_##name)->start(TIMER_##name)
670 
682 #define KMP_STOP_EXPLICIT_TIMER(name) \
683  __kmp_stats_thread_ptr->getExplicitTimer(EXPLICIT_TIMER_##name)->stop(TIMER_##name)
684 
699 #define KMP_OUTPUT_STATS(heading_string) \
700  __kmp_output_stats(heading_string)
701 
709 #define KMP_RESET_STATS() __kmp_reset_stats()
710 
711 #else // KMP_STATS_ENABLED
712 
713 // Null definitions
714 #define KMP_TIME_BLOCK(n) ((void)0)
715 #define KMP_COUNT_VALUE(n,v) ((void)0)
716 #define KMP_COUNT_BLOCK(n) ((void)0)
717 #define KMP_START_EXPLICIT_TIMER(n) ((void)0)
718 #define KMP_STOP_EXPLICIT_TIMER(n) ((void)0)
719 
720 #define KMP_OUTPUT_STATS(heading_string) ((void)0)
721 #define KMP_RESET_STATS() ((void)0)
722 
723 #endif // KMP_STATS_ENABLED
724 
725 #endif // KMP_STATS_H
#define KMP_FOREACH_TIMER(macro, arg)
Add new timers under KMP_FOREACH_TIMER() macro in kmp_stats.h.
Definition: kmp_stats.h:115
flags to describe the statistic ( timers or counter )
Definition: kmp_stats.h:59
static const int noUnits
statistic doesn't need units printed next to it in output
Definition: kmp_stats.h:62
static const int synthesized
statistic's value is created atexit time in the __kmp_output_stats function
Definition: kmp_stats.h:63
#define KMP_FOREACH_EXPLICIT_TIMER(macro, arg)
Add new explicit timers under KMP_FOREACH_EXPLICIT_TIMER() macro.
Definition: kmp_stats.h:204
static const int notInMaster
statistic is valid for non-master threads
Definition: kmp_stats.h:64
static const int onlyInMaster
statistic is valid only for master
Definition: kmp_stats.h:61
#define KMP_FOREACH_COUNTER(macro, arg)
Add new counters under KMP_FOREACH_COUNTER() macro in kmp_stats.h.
Definition: kmp_stats.h:84
static const int logEvent
statistic can be logged when KMP_STATS_EVENTS is on (valid only for timers)
Definition: kmp_stats.h:65