18 #include "kmp_config.h" 33 #include "kmp_stats_timing.h" 71 #define KMP_FOREACH_COUNTER(macro, arg) \ 72 macro (OMP_PARALLEL, stats_flags_e::onlyInMaster, arg) \ 73 macro (OMP_NESTED_PARALLEL, 0, arg) \ 74 macro (OMP_FOR_static, 0, arg) \ 75 macro (OMP_FOR_dynamic, 0, arg) \ 76 macro (OMP_DISTRIBUTE, 0, arg) \ 77 macro (OMP_BARRIER, 0, arg) \ 78 macro (OMP_CRITICAL,0, arg) \ 79 macro (OMP_SINGLE, 0, arg) \ 80 macro (OMP_MASTER, 0, arg) \ 81 macro (OMP_TEAMS, 0, arg) \ 82 macro (OMP_set_lock, 0, arg) \ 83 macro (OMP_test_lock, 0, arg) \ 84 macro (REDUCE_wait, 0, arg) \ 85 macro (REDUCE_nowait, 0, arg) \ 86 macro (OMP_TASKYIELD, 0, arg) \ 87 macro (TASK_executed, 0, arg) \ 88 macro (TASK_cancelled, 0, arg) \ 89 macro (TASK_stolen, 0, arg) \ 111 #define KMP_FOREACH_TIMER(macro, arg) \ 112 macro (OMP_start_end, stats_flags_e::onlyInMaster, arg) \ 113 macro (OMP_serial, stats_flags_e::onlyInMaster, arg) \ 114 macro (OMP_work, 0, arg) \ 115 macro (Total_work, stats_flags_e::synthesized, arg) \ 116 macro (OMP_barrier, 0, arg) \ 117 macro (Total_barrier, stats_flags_e::synthesized, arg) \ 118 macro (FOR_static_iterations, stats_flags_e::noUnits, arg) \ 119 macro (FOR_static_scheduling, 0, arg) \ 120 macro (FOR_dynamic_iterations, stats_flags_e::noUnits, arg) \ 121 macro (FOR_dynamic_scheduling, 0, arg) \ 122 macro (TASK_execution, 0, arg) \ 123 macro (OMP_set_numthreads, stats_flags_e::noUnits, arg) \ 124 macro (OMP_PARALLEL_args, stats_flags_e::noUnits, arg) \ 125 macro (OMP_single, 0, arg) \ 126 macro (OMP_master, 0, arg) \ 127 KMP_FOREACH_DEVELOPER_TIMER(macro, arg) \ 140 #if (KMP_DEVELOPER_STATS) 156 # define KMP_FOREACH_DEVELOPER_TIMER(macro, arg) \ 157 macro (KMP_fork_call, 0, arg) \ 158 macro (KMP_join_call, 0, arg) \ 159 macro (KMP_fork_barrier, stats_flags_e::logEvent, arg) \ 160 macro (KMP_join_barrier, stats_flags_e::logEvent, arg) \ 161 macro (KMP_barrier, 0, arg) \ 162 macro (KMP_end_split_barrier, 0, arg) \ 163 macro (KMP_hier_gather, 0, arg) \ 164 macro (KMP_hier_release, 0, arg) \ 165 macro (KMP_hyper_gather, stats_flags_e::logEvent, arg) \ 166 macro (KMP_hyper_release, stats_flags_e::logEvent, arg) \ 167 macro (KMP_linear_gather, 0, arg) \ 168 macro (KMP_linear_release, 0, arg) \ 169 macro (KMP_tree_gather, 0, arg) \ 170 macro (KMP_tree_release, 0, arg) \ 171 macro (USER_master_invoke, stats_flags_e::logEvent, arg) \ 172 macro (USER_worker_invoke, stats_flags_e::logEvent, arg) \ 173 macro (USER_resume, stats_flags_e::logEvent, arg) \ 174 macro (USER_suspend, stats_flags_e::logEvent, arg) \ 175 macro (USER_launch_thread_loop, stats_flags_e::logEvent, arg) \ 176 macro (KMP_allocate_team, 0, arg) \ 177 macro (KMP_setup_icv_copy, 0, arg) \ 178 macro (USER_icv_copy, 0, arg) 180 # define KMP_FOREACH_DEVELOPER_TIMER(macro, arg) 199 #define KMP_FOREACH_EXPLICIT_TIMER(macro, arg) \ 200 macro(OMP_serial, 0, arg) \ 201 macro(OMP_start_end, 0, arg) \ 202 macro(OMP_single, 0, arg) \ 203 macro(OMP_master, 0, arg) \ 204 KMP_FOREACH_EXPLICIT_DEVELOPER_TIMER(macro,arg) \ 207 #if (KMP_DEVELOPER_STATS) 208 # define KMP_FOREACH_EXPLICIT_DEVELOPER_TIMER(macro, arg) \ 209 macro(USER_launch_thread_loop, stats_flags_e::logEvent, arg) 211 # define KMP_FOREACH_EXPLICIT_DEVELOPER_TIMER(macro, arg) 214 #define ENUMERATE(name,ignore,prefix) prefix##name, 216 KMP_FOREACH_TIMER(ENUMERATE, TIMER_)
219 enum explicit_timer_e {
234 uint64_t sampleCount;
237 statistic() { reset(); }
238 statistic (statistic
const &o): minVal(o.minVal), maxVal(o.maxVal), meanVal(o.meanVal), m2(o.m2), sampleCount(o.sampleCount) {}
240 double getMin()
const {
return minVal; }
241 double getMean()
const {
return meanVal; }
242 double getMax()
const {
return maxVal; }
243 uint64_t getCount()
const {
return sampleCount; }
244 double getSD()
const {
return sqrt(m2/sampleCount); }
245 double getTotal()
const {
return sampleCount*meanVal; }
249 minVal = std::numeric_limits<double>::max();
250 maxVal = -std::numeric_limits<double>::max();
255 void addSample(
double sample);
256 void scale (
double factor);
257 void scaleDown(
double f) { scale (1./f); }
258 statistic & operator+= (statistic
const & other);
260 std::string format(
char unit,
bool total=
false)
const;
269 class timeStat :
public statistic
271 static statInfo timerInfo[];
274 timeStat() : statistic() {}
275 static const char * name(timer_e e) {
return timerInfo[e].name; }
281 static void clearEventFlags() {
283 for(i=0;i<TIMER_LAST;i++) {
295 tsc_tick_count startTime;
298 explicitTimer () : stat(0), startTime(0) { }
299 explicitTimer (timeStat * s) : stat(s), startTime() { }
301 void setStat (timeStat *s) { stat = s; }
302 void start(timer_e timerEnumValue);
303 void stop(timer_e timerEnumValue);
304 void reset() { startTime = 0; }
309 class blockTimer :
public explicitTimer
311 timer_e timerEnumValue;
313 blockTimer (timeStat * s, timer_e newTimerEnumValue) : timerEnumValue(newTimerEnumValue), explicitTimer(s) { start(timerEnumValue); }
314 ~blockTimer() { stop(timerEnumValue); }
322 static const statInfo counterInfo[];
325 counter() : value(0) {}
326 void increment() { value++; }
327 uint64_t getValue()
const {
return value; }
328 void reset() { value = 0; }
329 static const char * name(counter_e e) {
return counterInfo[e].name; }
366 class kmp_stats_event {
372 kmp_stats_event() : start(0), stop(0), nest_level(0), timer_name(TIMER_LAST) {}
373 kmp_stats_event(uint64_t strt, uint64_t stp,
int nst, timer_e nme) : start(strt), stop(stp), nest_level(nst), timer_name(nme) {}
374 inline uint64_t getStart()
const {
return start; }
375 inline uint64_t getStop()
const {
return stop; }
376 inline int getNestLevel()
const {
return nest_level; }
377 inline timer_e getTimerName()
const {
return timer_name; }
406 class kmp_stats_event_vector {
407 kmp_stats_event* events;
410 static const int INIT_SIZE = 1024;
412 kmp_stats_event_vector() {
413 events = (kmp_stats_event*)__kmp_allocate(
sizeof(kmp_stats_event)*INIT_SIZE);
415 allocated_size = INIT_SIZE;
417 ~kmp_stats_event_vector() {}
418 inline void reset() { internal_size = 0; }
419 inline int size()
const {
return internal_size; }
420 void push_back(uint64_t start_time, uint64_t stop_time,
int nest_level, timer_e name) {
422 if(internal_size == allocated_size) {
423 kmp_stats_event* tmp = (kmp_stats_event*)__kmp_allocate(
sizeof(kmp_stats_event)*allocated_size*2);
424 for(i=0;i<internal_size;i++) tmp[i] = events[i];
429 events[internal_size] = kmp_stats_event(start_time, stop_time, nest_level, name);
435 const kmp_stats_event & operator[](
int index)
const {
return events[index]; }
436 kmp_stats_event & operator[](
int index) {
return events[index]; }
437 const kmp_stats_event & at(
int index)
const {
return events[index]; }
438 kmp_stats_event & at(
int index) {
return events[index]; }
470 class kmp_stats_list {
472 timeStat _timers[TIMER_LAST+1];
473 counter _counters[COUNTER_LAST+1];
474 explicitTimer _explicitTimers[EXPLICIT_TIMER_LAST+1];
476 kmp_stats_event_vector _event_vector;
477 kmp_stats_list* next;
478 kmp_stats_list* prev;
480 kmp_stats_list() : next(
this) , prev(
this) , _event_vector(), _nestLevel(0) {
481 #define doInit(name,ignore1,ignore2) \ 482 getExplicitTimer(EXPLICIT_TIMER_##name)->setStat(getTimer(TIMER_##name)); 486 ~kmp_stats_list() { }
487 inline timeStat * getTimer(timer_e idx) {
return &_timers[idx]; }
488 inline counter * getCounter(counter_e idx) {
return &_counters[idx]; }
489 inline explicitTimer * getExplicitTimer(explicit_timer_e idx) {
return &_explicitTimers[idx]; }
490 inline timeStat * getTimers() {
return _timers; }
491 inline counter * getCounters() {
return _counters; }
492 inline explicitTimer * getExplicitTimers() {
return _explicitTimers; }
493 inline kmp_stats_event_vector & getEventVector() {
return _event_vector; }
494 inline void resetEventVector() { _event_vector.reset(); }
495 inline void incrementNestValue() { _nestLevel++; }
496 inline int getNestValue() {
return _nestLevel; }
497 inline void decrementNestValue() { _nestLevel--; }
498 inline int getGtid()
const {
return gtid; }
499 inline void setGtid(
int newgtid) { gtid = newgtid; }
500 kmp_stats_list* push_back(
int gtid);
501 inline void push_event(uint64_t start_time, uint64_t stop_time,
int nest_level, timer_e name) {
502 _event_vector.push_back(start_time, stop_time, nest_level, name);
506 kmp_stats_list::iterator begin();
507 kmp_stats_list::iterator end();
511 friend kmp_stats_list::iterator kmp_stats_list::begin();
512 friend kmp_stats_list::iterator kmp_stats_list::end();
516 iterator operator++();
517 iterator operator++(
int dummy);
518 iterator operator--();
519 iterator operator--(
int dummy);
520 bool operator!=(
const iterator & rhs);
521 bool operator==(
const iterator & rhs);
522 kmp_stats_list* operator*()
const;
555 class kmp_stats_output_module {
565 static const char* outputFileName;
566 static const char* eventsFileName;
567 static const char* plotFileName;
568 static int printPerThreadFlag;
569 static int printPerThreadEventsFlag;
570 static const rgb_color globalColorArray[];
571 static rgb_color timerColorInfo[];
574 static void setupEventColors();
575 static void printPloticusFile();
576 static void printStats(FILE *statsOut, statistic
const * theStats,
bool areTimers);
577 static void printCounters(FILE * statsOut, counter
const * theCounters);
578 static void printEvents(FILE * eventsOut, kmp_stats_event_vector* theEvents,
int gtid);
579 static rgb_color getEventColor(timer_e e) {
return timerColorInfo[e]; }
580 static void windupExplicitTimers();
581 bool eventPrintingEnabled() {
582 if(printPerThreadEventsFlag)
return true;
585 bool perThreadPrintingEnabled() {
586 if(printPerThreadFlag)
return true;
591 kmp_stats_output_module() { init(); }
592 void outputStats(
const char* heading);
598 void __kmp_stats_init();
599 void __kmp_reset_stats();
600 void __kmp_output_stats(
const char *);
601 void __kmp_accumulate_stats_at_exit(
void);
603 extern __thread kmp_stats_list* __kmp_stats_thread_ptr;
605 extern kmp_stats_list __kmp_stats_list;
607 extern kmp_tas_lock_t __kmp_stats_lock;
609 extern tsc_tick_count __kmp_stats_start_time;
611 extern kmp_stats_output_module __kmp_stats_output;
632 #define KMP_TIME_BLOCK(name) \ 633 blockTimer __BLOCKTIME__(__kmp_stats_thread_ptr->getTimer(TIMER_##name), TIMER_##name) 645 #define KMP_COUNT_VALUE(name, value) \ 646 __kmp_stats_thread_ptr->getTimer(TIMER_##name)->addSample(value) 657 #define KMP_COUNT_BLOCK(name) \ 658 __kmp_stats_thread_ptr->getCounter(COUNTER_##name)->increment() 671 #define KMP_START_EXPLICIT_TIMER(name) \ 672 __kmp_stats_thread_ptr->getExplicitTimer(EXPLICIT_TIMER_##name)->start(TIMER_##name) 685 #define KMP_STOP_EXPLICIT_TIMER(name) \ 686 __kmp_stats_thread_ptr->getExplicitTimer(EXPLICIT_TIMER_##name)->stop(TIMER_##name) 702 #define KMP_OUTPUT_STATS(heading_string) \ 703 __kmp_output_stats(heading_string) 712 #define KMP_RESET_STATS() __kmp_reset_stats() 714 #if (KMP_DEVELOPER_STATS) 715 # define KMP_TIME_DEVELOPER_BLOCK(n) KMP_TIME_BLOCK(n) 716 # define KMP_COUNT_DEVELOPER_VALUE(n,v) KMP_COUNT_VALUE(n,v) 717 # define KMP_COUNT_DEVELOPER_BLOCK(n) KMP_COUNT_BLOCK(n) 718 # define KMP_START_DEVELOPER_EXPLICIT_TIMER(n) KMP_START_EXPLICIT_TIMER(n) 719 # define KMP_STOP_DEVELOPER_EXPLICIT_TIMER(n) KMP_STOP_EXPLICIT_TIMER(n) 722 # define KMP_TIME_DEVELOPER_BLOCK(n) ((void)0) 723 # define KMP_COUNT_DEVELOPER_VALUE(n,v) ((void)0) 724 # define KMP_COUNT_DEVELOPER_BLOCK(n) ((void)0) 725 # define KMP_START_DEVELOPER_EXPLICIT_TIMER(n) ((void)0) 726 # define KMP_STOP_DEVELOPER_EXPLICIT_TIMER(n) ((void)0) 729 #else // KMP_STATS_ENABLED 732 #define KMP_TIME_BLOCK(n) ((void)0) 733 #define KMP_COUNT_VALUE(n,v) ((void)0) 734 #define KMP_COUNT_BLOCK(n) ((void)0) 735 #define KMP_START_EXPLICIT_TIMER(n) ((void)0) 736 #define KMP_STOP_EXPLICIT_TIMER(n) ((void)0) 738 #define KMP_OUTPUT_STATS(heading_string) ((void)0) 739 #define KMP_RESET_STATS() ((void)0) 741 #define KMP_TIME_DEVELOPER_BLOCK(n) ((void)0) 742 #define KMP_COUNT_DEVELOPER_VALUE(n,v) ((void)0) 743 #define KMP_COUNT_DEVELOPER_BLOCK(n) ((void)0) 744 #define KMP_START_DEVELOPER_EXPLICIT_TIMER(n) ((void)0) 745 #define KMP_STOP_DEVELOPER_EXPLICIT_TIMER(n) ((void)0) 746 #endif // KMP_STATS_ENABLED 748 #endif // KMP_STATS_H flags to describe the statistic ( timers or counter )
static const int noUnits
statistic doesn't need units printed next to it in output
static const int synthesized
statistic's value is created atexit time in the __kmp_output_stats function
#define KMP_FOREACH_EXPLICIT_TIMER(macro, arg)
Add new explicit timers under KMP_FOREACH_EXPLICIT_TIMER() macro.
static const int notInMaster
statistic is valid for non-master threads
static const int onlyInMaster
statistic is valid only for master
#define KMP_FOREACH_COUNTER(macro, arg)
Add new counters under KMP_FOREACH_COUNTER() macro in kmp_stats.h.
static const int logEvent
statistic can be logged when KMP_STATS_EVENTS is on (valid only for timers)