18 #include "kmp_stats.h" 25 #define STRINGIZE2(x) #x 26 #define STRINGIZE(x) STRINGIZE2(x) 28 #define expandName(name,flags,ignore) {STRINGIZE(name),flags}, 29 statInfo timeStat::timerInfo[] = {
30 KMP_FOREACH_TIMER(expandName,0)
33 const statInfo counter::counterInfo[] = {
39 #define expandName(ignore1,ignore2,ignore3) {0.0,0.0,0.0}, 40 kmp_stats_output_module::rgb_color kmp_stats_output_module::timerColorInfo[] = {
41 KMP_FOREACH_TIMER(expandName,0)
46 const kmp_stats_output_module::rgb_color kmp_stats_output_module::globalColorArray[] = {
70 static uint32_t statsPrinted = 0;
73 static kmp_stats_output_module __kmp_stats_global_output;
78 void statistic::addSample(
double sample)
80 double delta = sample - meanVal;
82 sampleCount = sampleCount + 1;
83 meanVal = meanVal + delta/sampleCount;
84 m2 = m2 + delta*(sample - meanVal);
86 minVal = std::min(minVal, sample);
87 maxVal = std::max(maxVal, sample);
90 statistic & statistic::operator+= (
const statistic & other)
98 uint64_t newSampleCount = sampleCount + other.sampleCount;
99 double dnsc = double(newSampleCount);
100 double dsc = double(sampleCount);
101 double dscBydnsc = dsc/dnsc;
102 double dosc = double(other.sampleCount);
103 double delta = other.meanVal - meanVal;
110 meanVal = meanVal*dscBydnsc + other.meanVal*(1-dscBydnsc);
111 m2 = m2 + other.m2 + dscBydnsc*dosc*delta*delta;
112 minVal = std::min (minVal, other.minVal);
113 maxVal = std::max (maxVal, other.maxVal);
114 sampleCount = newSampleCount;
120 void statistic::scale(
double factor)
122 minVal = minVal*factor;
123 maxVal = maxVal*factor;
124 meanVal= meanVal*factor;
125 m2 = m2*factor*factor;
129 std::string statistic::format(
char unit,
bool total)
const 131 std::string result = formatSI(sampleCount,9,
' ');
133 result = result + std::string(
", ") + formatSI(minVal, 9, unit);
134 result = result + std::string(
", ") + formatSI(meanVal, 9, unit);
135 result = result + std::string(
", ") + formatSI(maxVal, 9, unit);
137 result = result + std::string(
", ") + formatSI(meanVal*sampleCount, 9, unit);
138 result = result + std::string(
", ") + formatSI(getSD(), 9, unit);
146 void explicitTimer::start(timer_e timerEnumValue) {
147 startTime = tsc_tick_count::now();
148 if(timeStat::logEvent(timerEnumValue)) {
149 __kmp_stats_thread_ptr->incrementNestValue();
154 void explicitTimer::stop(timer_e timerEnumValue) {
155 if (startTime.getValue() == 0)
158 tsc_tick_count finishTime = tsc_tick_count::now();
161 stat->addSample ((finishTime - startTime).ticks());
163 if(timeStat::logEvent(timerEnumValue)) {
164 __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);
165 __kmp_stats_thread_ptr->decrementNestValue();
176 void kmp_stats_event_vector::deallocate() {
187 int compare_two_events(
const void* event1,
const void* event2) {
188 kmp_stats_event* ev1 = (kmp_stats_event*)event1;
189 kmp_stats_event* ev2 = (kmp_stats_event*)event2;
191 if(ev1->getStart() < ev2->getStart())
return -1;
192 else if(ev1->getStart() > ev2->getStart())
return 1;
196 void kmp_stats_event_vector::sort() {
197 qsort(events, internal_size,
sizeof(kmp_stats_event), compare_two_events);
204 kmp_stats_list* kmp_stats_list::push_back(
int gtid) {
205 kmp_stats_list* newnode = (kmp_stats_list*)__kmp_allocate(
sizeof(kmp_stats_list));
207 new (newnode) kmp_stats_list();
208 newnode->setGtid(gtid);
209 newnode->prev = this->prev;
210 newnode->next =
this;
211 newnode->prev->next = newnode;
212 newnode->next->prev = newnode;
215 void kmp_stats_list::deallocate() {
216 kmp_stats_list* ptr = this->next;
217 kmp_stats_list* delptr = this->next;
222 delptr->_event_vector.deallocate();
223 delptr->~kmp_stats_list();
227 kmp_stats_list::iterator kmp_stats_list::begin() {
228 kmp_stats_list::iterator it;
232 kmp_stats_list::iterator kmp_stats_list::end() {
233 kmp_stats_list::iterator it;
237 int kmp_stats_list::size() {
239 kmp_stats_list::iterator it;
240 for(retval=0, it=begin(); it!=end(); it++, retval++) {}
247 kmp_stats_list::iterator::iterator() : ptr(NULL) {}
248 kmp_stats_list::iterator::~iterator() {}
249 kmp_stats_list::iterator kmp_stats_list::iterator::operator++() {
250 this->ptr = this->ptr->next;
253 kmp_stats_list::iterator kmp_stats_list::iterator::operator++(
int dummy) {
254 this->ptr = this->ptr->next;
257 kmp_stats_list::iterator kmp_stats_list::iterator::operator--() {
258 this->ptr = this->ptr->prev;
261 kmp_stats_list::iterator kmp_stats_list::iterator::operator--(
int dummy) {
262 this->ptr = this->ptr->prev;
265 bool kmp_stats_list::iterator::operator!=(
const kmp_stats_list::iterator & rhs) {
266 return this->ptr!=rhs.ptr;
268 bool kmp_stats_list::iterator::operator==(
const kmp_stats_list::iterator & rhs) {
269 return this->ptr==rhs.ptr;
271 kmp_stats_list* kmp_stats_list::iterator::operator*()
const {
278 const char* kmp_stats_output_module::outputFileName = NULL;
279 const char* kmp_stats_output_module::eventsFileName = NULL;
280 const char* kmp_stats_output_module::plotFileName = NULL;
281 int kmp_stats_output_module::printPerThreadFlag = 0;
282 int kmp_stats_output_module::printPerThreadEventsFlag = 0;
285 void kmp_stats_output_module::init()
287 char * statsFileName = getenv(
"KMP_STATS_FILE");
288 eventsFileName = getenv(
"KMP_STATS_EVENTS_FILE");
289 plotFileName = getenv(
"KMP_STATS_PLOT_FILE");
290 char * threadStats = getenv(
"KMP_STATS_THREADS");
291 char * threadEvents = getenv(
"KMP_STATS_EVENTS");
294 outputFileName = statsFileName;
295 eventsFileName = eventsFileName ? eventsFileName :
"events.dat";
296 plotFileName = plotFileName ? plotFileName :
"events.plt";
299 printPerThreadFlag = __kmp_str_match_true(threadStats);
300 printPerThreadEventsFlag = __kmp_str_match_true(threadEvents);
302 if(printPerThreadEventsFlag) {
307 timeStat::clearEventFlags();
313 void kmp_stats_output_module::setupEventColors() {
315 int globalColorIndex = 0;
316 int numGlobalColors =
sizeof(globalColorArray) /
sizeof(rgb_color);
317 for(i=0;i<TIMER_LAST;i++) {
318 if(timeStat::logEvent((timer_e)i)) {
319 timerColorInfo[i] = globalColorArray[globalColorIndex];
320 globalColorIndex = (globalColorIndex+1)%numGlobalColors;
326 void kmp_stats_output_module::printStats(FILE *statsOut, statistic
const * theStats,
bool areTimers)
332 bool haveTimers =
false;
333 for (
int s = 0; s<TIMER_LAST; s++)
335 if (theStats[s].getCount() != 0)
346 const char * title = areTimers ?
"Timer, SampleCount," :
"Counter, ThreadCount,";
347 fprintf (statsOut,
"%s Min, Mean, Max, Total, SD\n", title);
349 for (
int s = 0; s<TIMER_LAST; s++) {
350 statistic
const * stat = &theStats[s];
351 if (stat->getCount() != 0) {
352 char tag = timeStat::noUnits(timer_e(s)) ?
' ' :
'T';
353 fprintf (statsOut,
"%-25s, %s\n", timeStat::name(timer_e(s)), stat->format(tag,
true).c_str());
357 for (
int s = 0; s<COUNTER_LAST; s++) {
358 statistic
const * stat = &theStats[s];
359 fprintf (statsOut,
"%-25s, %s\n", counter::name(counter_e(s)), stat->format(
' ',
true).c_str());
364 void kmp_stats_output_module::printCounters(FILE * statsOut, counter
const * theCounters)
368 fprintf (statsOut,
"\nCounter, Count\n");
369 for (
int c = 0; c<COUNTER_LAST; c++) {
370 counter
const * stat = &theCounters[c];
371 fprintf (statsOut,
"%-25s, %s\n", counter::name(counter_e(c)), formatSI(stat->getValue(), 9,
' ').c_str());
375 void kmp_stats_output_module::printEvents(FILE* eventsOut, kmp_stats_event_vector* theEvents,
int gtid) {
378 for (
int i = 0; i < theEvents->size(); i++) {
379 kmp_stats_event ev = theEvents->at(i);
380 rgb_color color = getEventColor(ev.getTimerName());
381 fprintf(eventsOut,
"%d %lu %lu %1.1f rgb(%1.1f,%1.1f,%1.1f) %s\n",
385 1.2 - (ev.getNestLevel() * 0.2),
386 color.r, color.g, color.b,
387 timeStat::name(ev.getTimerName())
393 void kmp_stats_output_module::windupExplicitTimers()
398 kmp_stats_list::iterator it;
399 for(it = __kmp_stats_list.begin(); it != __kmp_stats_list.end(); it++) {
400 for (
int timer=0; timer<EXPLICIT_TIMER_LAST; timer++) {
401 (*it)->getExplicitTimer(explicit_timer_e(timer))->stop((timer_e)timer);
406 void kmp_stats_output_module::printPloticusFile() {
408 int size = __kmp_stats_list.size();
409 FILE* plotOut = fopen(plotFileName,
"w+");
411 fprintf(plotOut,
"#proc page\n" 415 fprintf(plotOut,
"#proc getdata\n" 419 fprintf(plotOut,
"#proc areadef\n" 420 " title: OpenMP Sampling Timeline\n" 421 " titledetails: align=center size=16\n" 422 " rectangle: 1 1 13 9\n" 423 " xautorange: datafield=2,3\n" 424 " yautorange: -1 %d\n\n",
427 fprintf(plotOut,
"#proc xaxis\n" 429 " stubdetails: size=12\n" 430 " label: Time (ticks)\n" 431 " labeldetails: size=14\n\n");
433 fprintf(plotOut,
"#proc yaxis\n" 436 " stubdetails: size=12\n" 438 " labeldetails: size=14\n\n",
441 fprintf(plotOut,
"#proc bars\n" 442 " exactcolorfield: 5\n" 445 " segmentfields: 2 3\n" 446 " barwidthfield: 4\n\n");
449 for(i=0;i<TIMER_LAST;i++) {
450 if(timeStat::logEvent((timer_e)i)) {
451 rgb_color c = getEventColor((timer_e)i);
452 fprintf(plotOut,
"#proc legendentry\n" 453 " sampletype: color\n" 455 " details: rgb(%1.1f,%1.1f,%1.1f)\n\n",
456 timeStat::name((timer_e)i),
462 fprintf(plotOut,
"#proc legend\n" 464 " location: max max\n\n");
469 void kmp_stats_output_module::outputStats(
const char* heading)
471 statistic allStats[TIMER_LAST];
472 statistic allCounters[COUNTER_LAST];
475 windupExplicitTimers();
478 FILE * statsOut = outputFileName ? fopen (outputFileName,
"a+") : stderr;
480 if (eventPrintingEnabled()) {
481 eventsOut = fopen(eventsFileName,
"w+");
487 fprintf(statsOut,
"%s\n",heading);
489 kmp_stats_list::iterator it;
490 for (it = __kmp_stats_list.begin(); it != __kmp_stats_list.end(); it++) {
491 int t = (*it)->getGtid();
493 if (perThreadPrintingEnabled()) {
494 fprintf (statsOut,
"Thread %d\n", t);
495 printStats(statsOut, (*it)->getTimers(),
true);
496 printCounters(statsOut, (*it)->getCounters());
497 fprintf(statsOut,
"\n");
500 if (eventPrintingEnabled()) {
501 kmp_stats_event_vector events = (*it)->getEventVector();
502 printEvents(eventsOut, &events, t);
505 for (
int s = 0; s<TIMER_LAST; s++) {
507 if ((timeStat::masterOnly(timer_e(s)) && (t != 0)) ||
508 (timeStat::workerOnly(timer_e(s)) && (t == 0)) ||
509 timeStat::synthesized(timer_e(s))
515 statistic * threadStat = (*it)->getTimer(timer_e(s));
516 allStats[s] += *threadStat;
527 allStats[TIMER_Total_work].addSample ((*it)->getTimer(TIMER_OMP_work)->getTotal());
530 allStats[TIMER_Total_barrier].addSample ((*it)->getTimer(TIMER_OMP_barrier)->getTotal());
532 for (
int c = 0; c<COUNTER_LAST; c++) {
533 if (counter::masterOnly(counter_e(c)) && t != 0)
535 allCounters[c].addSample ((*it)->getCounter(counter_e(c))->getValue());
539 if (eventPrintingEnabled()) {
544 fprintf (statsOut,
"Aggregate for all threads\n");
545 printStats (statsOut, &allStats[0],
true);
546 fprintf (statsOut,
"\n");
547 printStats (statsOut, &allCounters[0],
false);
549 if (statsOut != stderr)
560 void __kmp_reset_stats()
562 kmp_stats_list::iterator it;
563 for(it = __kmp_stats_list.begin(); it != __kmp_stats_list.end(); it++) {
564 timeStat * timers = (*it)->getTimers();
565 counter * counters = (*it)->getCounters();
566 explicitTimer * eTimers = (*it)->getExplicitTimers();
568 for (
int t = 0; t<TIMER_LAST; t++)
571 for (
int c = 0; c<COUNTER_LAST; c++)
574 for (
int t=0; t<EXPLICIT_TIMER_LAST; t++)
578 (*it)->resetEventVector();
587 void __kmp_output_stats(
const char * heading)
589 __kmp_stats_global_output.outputStats(heading);
593 void __kmp_accumulate_stats_at_exit(
void)
596 if (KMP_XCHG_FIXED32(&statsPrinted, 1) != 0)
599 __kmp_output_stats(
"Statistics on exit");
603 void __kmp_stats_init(
void)
#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.