40 #include "kmp_stats.h"
47 #define STRINGIZE2(x) #x
48 #define STRINGIZE(x) STRINGIZE2(x)
50 #define expandName(name,flags,ignore) {STRINGIZE(name),flags},
51 statInfo timeStat::timerInfo[] = {
55 const statInfo counter::counterInfo[] = {
61 #define expandName(ignore1,ignore2,ignore3) {0.0,0.0,0.0},
62 kmp_stats_output_module::rgb_color kmp_stats_output_module::timerColorInfo[] = {
68 const kmp_stats_output_module::rgb_color kmp_stats_output_module::globalColorArray[] = {
92 static uint32_t statsPrinted = 0;
95 static kmp_stats_output_module __kmp_stats_global_output;
100 void statistic::addSample(
double sample)
102 double delta = sample - meanVal;
104 sampleCount = sampleCount + 1;
105 meanVal = meanVal + delta/sampleCount;
106 m2 = m2 + delta*(sample - meanVal);
108 minVal = std::min(minVal, sample);
109 maxVal = std::max(maxVal, sample);
112 statistic & statistic::operator+= (
const statistic & other)
114 if (sampleCount == 0)
120 uint64_t newSampleCount = sampleCount + other.sampleCount;
121 double dnsc = double(newSampleCount);
122 double dsc = double(sampleCount);
123 double dscBydnsc = dsc/dnsc;
124 double dosc = double(other.sampleCount);
125 double delta = other.meanVal - meanVal;
132 meanVal = meanVal*dscBydnsc + other.meanVal*(1-dscBydnsc);
133 m2 = m2 + other.m2 + dscBydnsc*dosc*delta*delta;
134 minVal = std::min (minVal, other.minVal);
135 maxVal = std::max (maxVal, other.maxVal);
136 sampleCount = newSampleCount;
142 void statistic::scale(
double factor)
144 minVal = minVal*factor;
145 maxVal = maxVal*factor;
146 meanVal= meanVal*factor;
147 m2 = m2*factor*factor;
151 std::string statistic::format(
char unit,
bool total)
const
153 std::string result = formatSI(sampleCount,9,
' ');
155 result = result + std::string(
", ") + formatSI(minVal, 9, unit);
156 result = result + std::string(
", ") + formatSI(meanVal, 9, unit);
157 result = result + std::string(
", ") + formatSI(maxVal, 9, unit);
159 result = result + std::string(
", ") + formatSI(meanVal*sampleCount, 9, unit);
160 result = result + std::string(
", ") + formatSI(getSD(), 9, unit);
168 void explicitTimer::start(timer_e timerEnumValue) {
169 startTime = tsc_tick_count::now();
170 if(timeStat::logEvent(timerEnumValue)) {
171 __kmp_stats_thread_ptr->incrementNestValue();
176 void explicitTimer::stop(timer_e timerEnumValue) {
177 if (startTime.getValue() == 0)
180 tsc_tick_count finishTime = tsc_tick_count::now();
183 stat->addSample ((finishTime - startTime).ticks());
185 if(timeStat::logEvent(timerEnumValue)) {
186 __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);
187 __kmp_stats_thread_ptr->decrementNestValue();
198 void kmp_stats_event_vector::deallocate() {
209 int compare_two_events(
const void* event1,
const void* event2) {
210 kmp_stats_event* ev1 = (kmp_stats_event*)event1;
211 kmp_stats_event* ev2 = (kmp_stats_event*)event2;
213 if(ev1->getStart() < ev2->getStart())
return -1;
214 else if(ev1->getStart() > ev2->getStart())
return 1;
218 void kmp_stats_event_vector::sort() {
219 qsort(events, internal_size,
sizeof(kmp_stats_event), compare_two_events);
226 kmp_stats_list* kmp_stats_list::push_back(
int gtid) {
227 kmp_stats_list* newnode = (kmp_stats_list*)__kmp_allocate(
sizeof(kmp_stats_list));
229 new (newnode) kmp_stats_list();
230 newnode->setGtid(gtid);
231 newnode->prev = this->prev;
232 newnode->next =
this;
233 newnode->prev->next = newnode;
234 newnode->next->prev = newnode;
237 void kmp_stats_list::deallocate() {
238 kmp_stats_list* ptr = this->next;
239 kmp_stats_list* delptr = this->next;
244 delptr->_event_vector.deallocate();
245 delptr->~kmp_stats_list();
249 kmp_stats_list::iterator kmp_stats_list::begin() {
250 kmp_stats_list::iterator it;
254 kmp_stats_list::iterator kmp_stats_list::end() {
255 kmp_stats_list::iterator it;
259 int kmp_stats_list::size() {
261 kmp_stats_list::iterator it;
262 for(retval=0, it=begin(); it!=end(); it++, retval++) {}
269 kmp_stats_list::iterator::iterator() : ptr(NULL) {}
270 kmp_stats_list::iterator::~iterator() {}
271 kmp_stats_list::iterator kmp_stats_list::iterator::operator++() {
272 this->ptr = this->ptr->next;
275 kmp_stats_list::iterator kmp_stats_list::iterator::operator++(
int dummy) {
276 this->ptr = this->ptr->next;
279 kmp_stats_list::iterator kmp_stats_list::iterator::operator--() {
280 this->ptr = this->ptr->prev;
283 kmp_stats_list::iterator kmp_stats_list::iterator::operator--(
int dummy) {
284 this->ptr = this->ptr->prev;
287 bool kmp_stats_list::iterator::operator!=(
const kmp_stats_list::iterator & rhs) {
288 return this->ptr!=rhs.ptr;
290 bool kmp_stats_list::iterator::operator==(
const kmp_stats_list::iterator & rhs) {
291 return this->ptr==rhs.ptr;
293 kmp_stats_list* kmp_stats_list::iterator::operator*()
const {
300 const char* kmp_stats_output_module::outputFileName = NULL;
301 const char* kmp_stats_output_module::eventsFileName = NULL;
302 const char* kmp_stats_output_module::plotFileName = NULL;
303 int kmp_stats_output_module::printPerThreadFlag = 0;
304 int kmp_stats_output_module::printPerThreadEventsFlag = 0;
307 void kmp_stats_output_module::init()
309 char * statsFileName = getenv(
"KMP_STATS_FILE");
310 eventsFileName = getenv(
"KMP_STATS_EVENTS_FILE");
311 plotFileName = getenv(
"KMP_STATS_PLOT_FILE");
312 char * threadStats = getenv(
"KMP_STATS_THREADS");
313 char * threadEvents = getenv(
"KMP_STATS_EVENTS");
316 outputFileName = statsFileName;
317 eventsFileName = eventsFileName ? eventsFileName :
"events.dat";
318 plotFileName = plotFileName ? plotFileName :
"events.plt";
321 printPerThreadFlag = __kmp_str_match_true(threadStats);
322 printPerThreadEventsFlag = __kmp_str_match_true(threadEvents);
324 if(printPerThreadEventsFlag) {
329 timeStat::clearEventFlags();
335 void kmp_stats_output_module::setupEventColors() {
337 int globalColorIndex = 0;
338 int numGlobalColors =
sizeof(globalColorArray) /
sizeof(rgb_color);
339 for(i=0;i<TIMER_LAST;i++) {
340 if(timeStat::logEvent((timer_e)i)) {
341 timerColorInfo[i] = globalColorArray[globalColorIndex];
342 globalColorIndex = (globalColorIndex+1)%numGlobalColors;
348 void kmp_stats_output_module::printStats(FILE *statsOut, statistic
const * theStats,
bool areTimers)
354 bool haveTimers =
false;
355 for (
int s = 0; s<TIMER_LAST; s++)
357 if (theStats[s].getCount() != 0)
368 const char * title = areTimers ?
"Timer, SampleCount," :
"Counter, ThreadCount,";
369 fprintf (statsOut,
"%s Min, Mean, Max, Total, SD\n", title);
371 for (
int s = 0; s<TIMER_LAST; s++) {
372 statistic
const * stat = &theStats[s];
373 if (stat->getCount() != 0) {
374 char tag = timeStat::noUnits(timer_e(s)) ?
' ' :
'T';
375 fprintf (statsOut,
"%-25s, %s\n", timeStat::name(timer_e(s)), stat->format(tag,
true).c_str());
379 for (
int s = 0; s<COUNTER_LAST; s++) {
380 statistic
const * stat = &theStats[s];
381 fprintf (statsOut,
"%-25s, %s\n", counter::name(counter_e(s)), stat->format(
' ',
true).c_str());
386 void kmp_stats_output_module::printCounters(FILE * statsOut, counter
const * theCounters)
390 fprintf (statsOut,
"\nCounter, Count\n");
391 for (
int c = 0; c<COUNTER_LAST; c++) {
392 counter
const * stat = &theCounters[c];
393 fprintf (statsOut,
"%-25s, %s\n", counter::name(counter_e(c)), formatSI(stat->getValue(), 9,
' ').c_str());
397 void kmp_stats_output_module::printEvents(FILE* eventsOut, kmp_stats_event_vector* theEvents,
int gtid) {
400 for (
int i = 0; i < theEvents->size(); i++) {
401 kmp_stats_event ev = theEvents->at(i);
402 rgb_color color = getEventColor(ev.getTimerName());
403 fprintf(eventsOut,
"%d %lu %lu %1.1f rgb(%1.1f,%1.1f,%1.1f) %s\n",
407 1.2 - (ev.getNestLevel() * 0.2),
408 color.r, color.g, color.b,
409 timeStat::name(ev.getTimerName())
415 void kmp_stats_output_module::windupExplicitTimers()
420 kmp_stats_list::iterator it;
421 for(it = __kmp_stats_list.begin(); it != __kmp_stats_list.end(); it++) {
422 for (
int timer=0; timer<EXPLICIT_TIMER_LAST; timer++) {
423 (*it)->getExplicitTimer(explicit_timer_e(timer))->stop((timer_e)timer);
428 void kmp_stats_output_module::printPloticusFile() {
430 int size = __kmp_stats_list.size();
431 FILE* plotOut = fopen(plotFileName,
"w+");
433 fprintf(plotOut,
"#proc page\n"
437 fprintf(plotOut,
"#proc getdata\n"
441 fprintf(plotOut,
"#proc areadef\n"
442 " title: OpenMP Sampling Timeline\n"
443 " titledetails: align=center size=16\n"
444 " rectangle: 1 1 13 9\n"
445 " xautorange: datafield=2,3\n"
446 " yautorange: -1 %d\n\n",
449 fprintf(plotOut,
"#proc xaxis\n"
451 " stubdetails: size=12\n"
452 " label: Time (ticks)\n"
453 " labeldetails: size=14\n\n");
455 fprintf(plotOut,
"#proc yaxis\n"
458 " stubdetails: size=12\n"
460 " labeldetails: size=14\n\n",
463 fprintf(plotOut,
"#proc bars\n"
464 " exactcolorfield: 5\n"
467 " segmentfields: 2 3\n"
468 " barwidthfield: 4\n\n");
471 for(i=0;i<TIMER_LAST;i++) {
472 if(timeStat::logEvent((timer_e)i)) {
473 rgb_color c = getEventColor((timer_e)i);
474 fprintf(plotOut,
"#proc legendentry\n"
475 " sampletype: color\n"
477 " details: rgb(%1.1f,%1.1f,%1.1f)\n\n",
478 timeStat::name((timer_e)i),
484 fprintf(plotOut,
"#proc legend\n"
486 " location: max max\n\n");
491 void kmp_stats_output_module::outputStats(
const char* heading)
493 statistic allStats[TIMER_LAST];
494 statistic allCounters[COUNTER_LAST];
497 windupExplicitTimers();
500 FILE * statsOut = outputFileName ? fopen (outputFileName,
"a+") : stderr;
502 if (eventPrintingEnabled()) {
503 eventsOut = fopen(eventsFileName,
"w+");
509 fprintf(statsOut,
"%s\n",heading);
511 kmp_stats_list::iterator it;
512 for (it = __kmp_stats_list.begin(); it != __kmp_stats_list.end(); it++) {
513 int t = (*it)->getGtid();
515 if (perThreadPrintingEnabled()) {
516 fprintf (statsOut,
"Thread %d\n", t);
517 printStats(statsOut, (*it)->getTimers(),
true);
518 printCounters(statsOut, (*it)->getCounters());
519 fprintf(statsOut,
"\n");
522 if (eventPrintingEnabled()) {
523 kmp_stats_event_vector events = (*it)->getEventVector();
524 printEvents(eventsOut, &events, t);
527 for (
int s = 0; s<TIMER_LAST; s++) {
529 if ((timeStat::masterOnly(timer_e(s)) && (t != 0)) ||
530 (timeStat::workerOnly(timer_e(s)) && (t == 0)) ||
531 timeStat::synthesized(timer_e(s))
537 statistic * threadStat = (*it)->getTimer(timer_e(s));
538 allStats[s] += *threadStat;
547 allStats[TIMER_Total_work].addSample ((*it)->getTimer(TIMER_OMP_work)->getTotal());
550 if ((t != 0) || !timeStat::workerOnly(timer_e(TIMER_OMP_await_work)))
551 allStats[TIMER_Total_await_work].addSample ((*it)->getTimer(TIMER_OMP_await_work)->getTotal());
554 allStats[TIMER_Total_barrier].addSample ((*it)->getTimer(TIMER_OMP_barrier)->getTotal());
556 for (
int c = 0; c<COUNTER_LAST; c++) {
557 if (counter::masterOnly(counter_e(c)) && t != 0)
559 allCounters[c].addSample ((*it)->getCounter(counter_e(c))->getValue());
563 if (eventPrintingEnabled()) {
568 fprintf (statsOut,
"Aggregate for all threads\n");
569 printStats (statsOut, &allStats[0],
true);
570 fprintf (statsOut,
"\n");
571 printStats (statsOut, &allCounters[0],
false);
573 if (statsOut != stderr)
584 void __kmp_reset_stats()
586 kmp_stats_list::iterator it;
587 for(it = __kmp_stats_list.begin(); it != __kmp_stats_list.end(); it++) {
588 timeStat * timers = (*it)->getTimers();
589 counter * counters = (*it)->getCounters();
590 explicitTimer * eTimers = (*it)->getExplicitTimers();
592 for (
int t = 0; t<TIMER_LAST; t++)
595 for (
int c = 0; c<COUNTER_LAST; c++)
598 for (
int t=0; t<EXPLICIT_TIMER_LAST; t++)
602 (*it)->resetEventVector();
611 void __kmp_output_stats(
const char * heading)
613 __kmp_stats_global_output.outputStats(heading);
617 void __kmp_accumulate_stats_at_exit(
void)
620 if (KMP_XCHG_FIXED32(&statsPrinted, 1) != 0)
623 __kmp_output_stats(
"Statistics on exit");
627 void __kmp_stats_init(
void)
634 #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.