21 #include "kmp_stats.h"
28 #define STRINGIZE2(x) #x
29 #define STRINGIZE(x) STRINGIZE2(x)
31 #define expandName(name,flags,ignore) {STRINGIZE(name),flags},
32 statInfo timeStat::timerInfo[] = {
36 const statInfo counter::counterInfo[] = {
42 #define expandName(ignore1,ignore2,ignore3) {0.0,0.0,0.0},
43 kmp_stats_output_module::rgb_color kmp_stats_output_module::timerColorInfo[] = {
49 const kmp_stats_output_module::rgb_color kmp_stats_output_module::globalColorArray[] = {
73 static uint32_t statsPrinted = 0;
76 static kmp_stats_output_module __kmp_stats_global_output;
81 void statistic::addSample(
double sample)
83 double delta = sample - meanVal;
85 sampleCount = sampleCount + 1;
86 meanVal = meanVal + delta/sampleCount;
87 m2 = m2 + delta*(sample - meanVal);
89 minVal = std::min(minVal, sample);
90 maxVal = std::max(maxVal, sample);
93 statistic & statistic::operator+= (
const statistic & other)
101 uint64_t newSampleCount = sampleCount + other.sampleCount;
102 double dnsc = double(newSampleCount);
103 double dsc = double(sampleCount);
104 double dscBydnsc = dsc/dnsc;
105 double dosc = double(other.sampleCount);
106 double delta = other.meanVal - meanVal;
113 meanVal = meanVal*dscBydnsc + other.meanVal*(1-dscBydnsc);
114 m2 = m2 + other.m2 + dscBydnsc*dosc*delta*delta;
115 minVal = std::min (minVal, other.minVal);
116 maxVal = std::max (maxVal, other.maxVal);
117 sampleCount = newSampleCount;
123 void statistic::scale(
double factor)
125 minVal = minVal*factor;
126 maxVal = maxVal*factor;
127 meanVal= meanVal*factor;
128 m2 = m2*factor*factor;
132 std::string statistic::format(
char unit,
bool total)
const
134 std::string result = formatSI(sampleCount,9,
' ');
136 result = result + std::string(
", ") + formatSI(minVal, 9, unit);
137 result = result + std::string(
", ") + formatSI(meanVal, 9, unit);
138 result = result + std::string(
", ") + formatSI(maxVal, 9, unit);
140 result = result + std::string(
", ") + formatSI(meanVal*sampleCount, 9, unit);
141 result = result + std::string(
", ") + formatSI(getSD(), 9, unit);
149 void explicitTimer::start(timer_e timerEnumValue) {
150 startTime = tsc_tick_count::now();
151 if(timeStat::logEvent(timerEnumValue)) {
152 __kmp_stats_thread_ptr->incrementNestValue();
157 void explicitTimer::stop(timer_e timerEnumValue) {
158 if (startTime.getValue() == 0)
161 tsc_tick_count finishTime = tsc_tick_count::now();
164 stat->addSample ((finishTime - startTime).ticks());
166 if(timeStat::logEvent(timerEnumValue)) {
167 __kmp_stats_thread_ptr->push_event(startTime.getValue() - __kmp_stats_start_time.getValue(), finishTime.getValue() - __kmp_stats_start_time.getValue(), __kmp_stats_thread_ptr->getNestValue(), timerEnumValue);
168 __kmp_stats_thread_ptr->decrementNestValue();
179 void kmp_stats_event_vector::deallocate() {
190 int compare_two_events(
const void* event1,
const void* event2) {
191 kmp_stats_event* ev1 = (kmp_stats_event*)event1;
192 kmp_stats_event* ev2 = (kmp_stats_event*)event2;
194 if(ev1->getStart() < ev2->getStart())
return -1;
195 else if(ev1->getStart() > ev2->getStart())
return 1;
199 void kmp_stats_event_vector::sort() {
200 qsort(events, internal_size,
sizeof(kmp_stats_event), compare_two_events);
207 kmp_stats_list* kmp_stats_list::push_back(
int gtid) {
208 kmp_stats_list* newnode = (kmp_stats_list*)__kmp_allocate(
sizeof(kmp_stats_list));
210 new (newnode) kmp_stats_list();
211 newnode->setGtid(gtid);
212 newnode->prev = this->prev;
213 newnode->next =
this;
214 newnode->prev->next = newnode;
215 newnode->next->prev = newnode;
218 void kmp_stats_list::deallocate() {
219 kmp_stats_list* ptr = this->next;
220 kmp_stats_list* delptr = this->next;
225 delptr->_event_vector.deallocate();
226 delptr->~kmp_stats_list();
230 kmp_stats_list::iterator kmp_stats_list::begin() {
231 kmp_stats_list::iterator it;
235 kmp_stats_list::iterator kmp_stats_list::end() {
236 kmp_stats_list::iterator it;
240 int kmp_stats_list::size() {
242 kmp_stats_list::iterator it;
243 for(retval=0, it=begin(); it!=end(); it++, retval++) {}
250 kmp_stats_list::iterator::iterator() : ptr(NULL) {}
251 kmp_stats_list::iterator::~iterator() {}
252 kmp_stats_list::iterator kmp_stats_list::iterator::operator++() {
253 this->ptr = this->ptr->next;
256 kmp_stats_list::iterator kmp_stats_list::iterator::operator++(
int dummy) {
257 this->ptr = this->ptr->next;
260 kmp_stats_list::iterator kmp_stats_list::iterator::operator--() {
261 this->ptr = this->ptr->prev;
264 kmp_stats_list::iterator kmp_stats_list::iterator::operator--(
int dummy) {
265 this->ptr = this->ptr->prev;
268 bool kmp_stats_list::iterator::operator!=(
const kmp_stats_list::iterator & rhs) {
269 return this->ptr!=rhs.ptr;
271 bool kmp_stats_list::iterator::operator==(
const kmp_stats_list::iterator & rhs) {
272 return this->ptr==rhs.ptr;
274 kmp_stats_list* kmp_stats_list::iterator::operator*()
const {
281 const char* kmp_stats_output_module::outputFileName = NULL;
282 const char* kmp_stats_output_module::eventsFileName = NULL;
283 const char* kmp_stats_output_module::plotFileName = NULL;
284 int kmp_stats_output_module::printPerThreadFlag = 0;
285 int kmp_stats_output_module::printPerThreadEventsFlag = 0;
288 void kmp_stats_output_module::init()
290 char * statsFileName = getenv(
"KMP_STATS_FILE");
291 eventsFileName = getenv(
"KMP_STATS_EVENTS_FILE");
292 plotFileName = getenv(
"KMP_STATS_PLOT_FILE");
293 char * threadStats = getenv(
"KMP_STATS_THREADS");
294 char * threadEvents = getenv(
"KMP_STATS_EVENTS");
297 outputFileName = statsFileName;
298 eventsFileName = eventsFileName ? eventsFileName :
"events.dat";
299 plotFileName = plotFileName ? plotFileName :
"events.plt";
302 printPerThreadFlag = __kmp_str_match_true(threadStats);
303 printPerThreadEventsFlag = __kmp_str_match_true(threadEvents);
305 if(printPerThreadEventsFlag) {
310 timeStat::clearEventFlags();
316 void kmp_stats_output_module::setupEventColors() {
318 int globalColorIndex = 0;
319 int numGlobalColors =
sizeof(globalColorArray) /
sizeof(rgb_color);
320 for(i=0;i<TIMER_LAST;i++) {
321 if(timeStat::logEvent((timer_e)i)) {
322 timerColorInfo[i] = globalColorArray[globalColorIndex];
323 globalColorIndex = (globalColorIndex+1)%numGlobalColors;
329 void kmp_stats_output_module::printStats(FILE *statsOut, statistic
const * theStats,
bool areTimers)
335 bool haveTimers =
false;
336 for (
int s = 0; s<TIMER_LAST; s++)
338 if (theStats[s].getCount() != 0)
349 const char * title = areTimers ?
"Timer, SampleCount," :
"Counter, ThreadCount,";
350 fprintf (statsOut,
"%s Min, Mean, Max, Total, SD\n", title);
352 for (
int s = 0; s<TIMER_LAST; s++) {
353 statistic
const * stat = &theStats[s];
354 if (stat->getCount() != 0) {
355 char tag = timeStat::noUnits(timer_e(s)) ?
' ' :
'T';
356 fprintf (statsOut,
"%-25s, %s\n", timeStat::name(timer_e(s)), stat->format(tag,
true).c_str());
360 for (
int s = 0; s<COUNTER_LAST; s++) {
361 statistic
const * stat = &theStats[s];
362 fprintf (statsOut,
"%-25s, %s\n", counter::name(counter_e(s)), stat->format(
' ',
true).c_str());
367 void kmp_stats_output_module::printCounters(FILE * statsOut, counter
const * theCounters)
371 fprintf (statsOut,
"\nCounter, Count\n");
372 for (
int c = 0; c<COUNTER_LAST; c++) {
373 counter
const * stat = &theCounters[c];
374 fprintf (statsOut,
"%-25s, %s\n", counter::name(counter_e(c)), formatSI(stat->getValue(), 9,
' ').c_str());
378 void kmp_stats_output_module::printEvents(FILE* eventsOut, kmp_stats_event_vector* theEvents,
int gtid) {
381 for (
int i = 0; i < theEvents->size(); i++) {
382 kmp_stats_event ev = theEvents->at(i);
383 rgb_color color = getEventColor(ev.getTimerName());
384 fprintf(eventsOut,
"%d %lu %lu %1.1f rgb(%1.1f,%1.1f,%1.1f) %s\n",
388 1.2 - (ev.getNestLevel() * 0.2),
389 color.r, color.g, color.b,
390 timeStat::name(ev.getTimerName())
396 void kmp_stats_output_module::windupExplicitTimers()
401 kmp_stats_list::iterator it;
402 for(it = __kmp_stats_list.begin(); it != __kmp_stats_list.end(); it++) {
403 for (
int timer=0; timer<EXPLICIT_TIMER_LAST; timer++) {
404 (*it)->getExplicitTimer(explicit_timer_e(timer))->stop((timer_e)timer);
409 void kmp_stats_output_module::printPloticusFile() {
411 int size = __kmp_stats_list.size();
412 FILE* plotOut = fopen(plotFileName,
"w+");
414 fprintf(plotOut,
"#proc page\n"
418 fprintf(plotOut,
"#proc getdata\n"
422 fprintf(plotOut,
"#proc areadef\n"
423 " title: OpenMP Sampling Timeline\n"
424 " titledetails: align=center size=16\n"
425 " rectangle: 1 1 13 9\n"
426 " xautorange: datafield=2,3\n"
427 " yautorange: -1 %d\n\n",
430 fprintf(plotOut,
"#proc xaxis\n"
432 " stubdetails: size=12\n"
433 " label: Time (ticks)\n"
434 " labeldetails: size=14\n\n");
436 fprintf(plotOut,
"#proc yaxis\n"
439 " stubdetails: size=12\n"
441 " labeldetails: size=14\n\n",
444 fprintf(plotOut,
"#proc bars\n"
445 " exactcolorfield: 5\n"
448 " segmentfields: 2 3\n"
449 " barwidthfield: 4\n\n");
452 for(i=0;i<TIMER_LAST;i++) {
453 if(timeStat::logEvent((timer_e)i)) {
454 rgb_color c = getEventColor((timer_e)i);
455 fprintf(plotOut,
"#proc legendentry\n"
456 " sampletype: color\n"
458 " details: rgb(%1.1f,%1.1f,%1.1f)\n\n",
459 timeStat::name((timer_e)i),
465 fprintf(plotOut,
"#proc legend\n"
467 " location: max max\n\n");
472 void kmp_stats_output_module::outputStats(
const char* heading)
474 statistic allStats[TIMER_LAST];
475 statistic allCounters[COUNTER_LAST];
478 windupExplicitTimers();
481 FILE * statsOut = outputFileName ? fopen (outputFileName,
"a+") : stderr;
483 if (eventPrintingEnabled()) {
484 eventsOut = fopen(eventsFileName,
"w+");
490 fprintf(statsOut,
"%s\n",heading);
492 kmp_stats_list::iterator it;
493 for (it = __kmp_stats_list.begin(); it != __kmp_stats_list.end(); it++) {
494 int t = (*it)->getGtid();
496 if (perThreadPrintingEnabled()) {
497 fprintf (statsOut,
"Thread %d\n", t);
498 printStats(statsOut, (*it)->getTimers(),
true);
499 printCounters(statsOut, (*it)->getCounters());
500 fprintf(statsOut,
"\n");
503 if (eventPrintingEnabled()) {
504 kmp_stats_event_vector events = (*it)->getEventVector();
505 printEvents(eventsOut, &events, t);
508 for (
int s = 0; s<TIMER_LAST; s++) {
510 if ((timeStat::masterOnly(timer_e(s)) && (t != 0)) ||
511 (timeStat::workerOnly(timer_e(s)) && (t == 0)) ||
512 timeStat::synthesized(timer_e(s))
518 statistic * threadStat = (*it)->getTimer(timer_e(s));
519 allStats[s] += *threadStat;
528 allStats[TIMER_Total_work].addSample ((*it)->getTimer(TIMER_OMP_work)->getTotal());
531 if ((t != 0) || !timeStat::workerOnly(timer_e(TIMER_OMP_await_work)))
532 allStats[TIMER_Total_await_work].addSample ((*it)->getTimer(TIMER_OMP_await_work)->getTotal());
535 allStats[TIMER_Total_barrier].addSample ((*it)->getTimer(TIMER_OMP_barrier)->getTotal());
537 for (
int c = 0; c<COUNTER_LAST; c++) {
538 if (counter::masterOnly(counter_e(c)) && t != 0)
540 allCounters[c].addSample ((*it)->getCounter(counter_e(c))->getValue());
544 if (eventPrintingEnabled()) {
549 fprintf (statsOut,
"Aggregate for all threads\n");
550 printStats (statsOut, &allStats[0],
true);
551 fprintf (statsOut,
"\n");
552 printStats (statsOut, &allCounters[0],
false);
554 if (statsOut != stderr)
565 void __kmp_reset_stats()
567 kmp_stats_list::iterator it;
568 for(it = __kmp_stats_list.begin(); it != __kmp_stats_list.end(); it++) {
569 timeStat * timers = (*it)->getTimers();
570 counter * counters = (*it)->getCounters();
571 explicitTimer * eTimers = (*it)->getExplicitTimers();
573 for (
int t = 0; t<TIMER_LAST; t++)
576 for (
int c = 0; c<COUNTER_LAST; c++)
579 for (
int t=0; t<EXPLICIT_TIMER_LAST; t++)
583 (*it)->resetEventVector();
592 void __kmp_output_stats(
const char * heading)
594 __kmp_stats_global_output.outputStats(heading);
598 void __kmp_accumulate_stats_at_exit(
void)
601 if (KMP_XCHG_FIXED32(&statsPrinted, 1) != 0)
604 __kmp_output_stats(
"Statistics on exit");
608 void __kmp_stats_init(
void)
615 #endif // KMP_STATS_ENABLED
#define KMP_FOREACH_TIMER(macro, arg)
Add new timers under KMP_FOREACH_TIMER() macro in kmp_stats.h.
#define KMP_START_EXPLICIT_TIMER(name)
"Starts" an explicit timer which will need a corresponding KMP_STOP_EXPLICIT_TIMER() macro...
#define KMP_FOREACH_COUNTER(macro, arg)
Add new counters under KMP_FOREACH_COUNTER() macro in kmp_stats.h.