14cc4bb4cSJim Cownie /** @file kmp_stats.cpp
24cc4bb4cSJim Cownie * Statistics gathering and processing.
34cc4bb4cSJim Cownie */
44cc4bb4cSJim Cownie
54cc4bb4cSJim Cownie //===----------------------------------------------------------------------===//
64cc4bb4cSJim Cownie //
757b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
857b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
957b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
104cc4bb4cSJim Cownie //
114cc4bb4cSJim Cownie //===----------------------------------------------------------------------===//
124cc4bb4cSJim Cownie
134cc4bb4cSJim Cownie #include "kmp.h"
144cc4bb4cSJim Cownie #include "kmp_lock.h"
154cc4bb4cSJim Cownie #include "kmp_stats.h"
163041982dSJonathan Peyton #include "kmp_str.h"
174cc4bb4cSJim Cownie
184cc4bb4cSJim Cownie #include <algorithm>
196e98d798SJonathan Peyton #include <ctime>
203041982dSJonathan Peyton #include <iomanip>
213041982dSJonathan Peyton #include <sstream>
223041982dSJonathan Peyton #include <stdlib.h> // for atexit
23f0682ac4SJonathan Peyton #include <cmath>
244cc4bb4cSJim Cownie
254cc4bb4cSJim Cownie #define STRINGIZE2(x) #x
264cc4bb4cSJim Cownie #define STRINGIZE(x) STRINGIZE2(x)
274cc4bb4cSJim Cownie
284cc4bb4cSJim Cownie #define expandName(name, flags, ignore) {STRINGIZE(name), flags},
294cc4bb4cSJim Cownie statInfo timeStat::timerInfo[] = {
303041982dSJonathan Peyton KMP_FOREACH_TIMER(expandName, 0){"TIMER_LAST", 0}};
314cc4bb4cSJim Cownie const statInfo counter::counterInfo[] = {
323041982dSJonathan Peyton KMP_FOREACH_COUNTER(expandName, 0){"COUNTER_LAST", 0}};
334cc4bb4cSJim Cownie #undef expandName
344cc4bb4cSJim Cownie
354cc4bb4cSJim Cownie #define expandName(ignore1, ignore2, ignore3) {0.0, 0.0, 0.0},
364cc4bb4cSJim Cownie kmp_stats_output_module::rgb_color kmp_stats_output_module::timerColorInfo[] = {
373041982dSJonathan Peyton KMP_FOREACH_TIMER(expandName, 0){0.0, 0.0, 0.0}};
384cc4bb4cSJim Cownie #undef expandName
394cc4bb4cSJim Cownie
403041982dSJonathan Peyton const kmp_stats_output_module::rgb_color
413041982dSJonathan Peyton kmp_stats_output_module::globalColorArray[] = {
424cc4bb4cSJim Cownie {1.0, 0.0, 0.0}, // red
434cc4bb4cSJim Cownie {1.0, 0.6, 0.0}, // orange
444cc4bb4cSJim Cownie {1.0, 1.0, 0.0}, // yellow
454cc4bb4cSJim Cownie {0.0, 1.0, 0.0}, // green
464cc4bb4cSJim Cownie {0.0, 0.0, 1.0}, // blue
474cc4bb4cSJim Cownie {0.6, 0.2, 0.8}, // purple
484cc4bb4cSJim Cownie {1.0, 0.0, 1.0}, // magenta
494cc4bb4cSJim Cownie {0.0, 0.4, 0.2}, // dark green
504cc4bb4cSJim Cownie {1.0, 1.0, 0.6}, // light yellow
514cc4bb4cSJim Cownie {0.6, 0.4, 0.6}, // dirty purple
524cc4bb4cSJim Cownie {0.0, 1.0, 1.0}, // cyan
534cc4bb4cSJim Cownie {1.0, 0.4, 0.8}, // pink
544cc4bb4cSJim Cownie {0.5, 0.5, 0.5}, // grey
554cc4bb4cSJim Cownie {0.8, 0.7, 0.5}, // brown
564cc4bb4cSJim Cownie {0.6, 0.6, 1.0}, // light blue
574cc4bb4cSJim Cownie {1.0, 0.7, 0.5}, // peach
584cc4bb4cSJim Cownie {0.8, 0.5, 1.0}, // lavender
594cc4bb4cSJim Cownie {0.6, 0.0, 0.0}, // dark red
604cc4bb4cSJim Cownie {0.7, 0.6, 0.0}, // gold
614cc4bb4cSJim Cownie {0.0, 0.0, 0.0} // black
624cc4bb4cSJim Cownie };
634cc4bb4cSJim Cownie
644cc4bb4cSJim Cownie // Ensure that the atexit handler only runs once.
654cc4bb4cSJim Cownie static uint32_t statsPrinted = 0;
664cc4bb4cSJim Cownie
674cc4bb4cSJim Cownie // output interface
685375fe82SJonathan Peyton static kmp_stats_output_module *__kmp_stats_global_output = NULL;
694cc4bb4cSJim Cownie
706b316febSTerry Wilmarth double logHistogram::binMax[] = {1.e1l, 1.e2l, 1.e3l, 1.e4l, 1.e5l, 1.e6l,
716b316febSTerry Wilmarth 1.e7l, 1.e8l, 1.e9l, 1.e10l, 1.e11l, 1.e12l,
726b316febSTerry Wilmarth 1.e13l, 1.e14l, 1.e15l, 1.e16l, 1.e17l, 1.e18l,
736b316febSTerry Wilmarth 1.e19l, 1.e20l, 1.e21l, 1.e22l, 1.e23l, 1.e24l,
746b316febSTerry Wilmarth 1.e25l, 1.e26l, 1.e27l, 1.e28l, 1.e29l, 1.e30l,
756b316febSTerry Wilmarth // Always have infinity be the last value
766b316febSTerry Wilmarth std::numeric_limits<double>::infinity()};
77f0682ac4SJonathan Peyton
784cc4bb4cSJim Cownie /* ************* statistic member functions ************* */
794cc4bb4cSJim Cownie
addSample(double sample)803041982dSJonathan Peyton void statistic::addSample(double sample) {
81f0682ac4SJonathan Peyton sample -= offset;
82f0682ac4SJonathan Peyton KMP_DEBUG_ASSERT(std::isfinite(sample));
83f0682ac4SJonathan Peyton
844cc4bb4cSJim Cownie double delta = sample - meanVal;
854cc4bb4cSJim Cownie
864cc4bb4cSJim Cownie sampleCount = sampleCount + 1;
874cc4bb4cSJim Cownie meanVal = meanVal + delta / sampleCount;
884cc4bb4cSJim Cownie m2 = m2 + delta * (sample - meanVal);
894cc4bb4cSJim Cownie
904cc4bb4cSJim Cownie minVal = std::min(minVal, sample);
914cc4bb4cSJim Cownie maxVal = std::max(maxVal, sample);
92f0682ac4SJonathan Peyton if (collectingHist)
93f0682ac4SJonathan Peyton hist.addSample(sample);
944cc4bb4cSJim Cownie }
954cc4bb4cSJim Cownie
operator +=(const statistic & other)963041982dSJonathan Peyton statistic &statistic::operator+=(const statistic &other) {
97f0682ac4SJonathan Peyton if (other.sampleCount == 0)
98f0682ac4SJonathan Peyton return *this;
99f0682ac4SJonathan Peyton
1003041982dSJonathan Peyton if (sampleCount == 0) {
1014cc4bb4cSJim Cownie *this = other;
1024cc4bb4cSJim Cownie return *this;
1034cc4bb4cSJim Cownie }
1044cc4bb4cSJim Cownie
1054cc4bb4cSJim Cownie uint64_t newSampleCount = sampleCount + other.sampleCount;
1064cc4bb4cSJim Cownie double dnsc = double(newSampleCount);
1074cc4bb4cSJim Cownie double dsc = double(sampleCount);
1084cc4bb4cSJim Cownie double dscBydnsc = dsc / dnsc;
1094cc4bb4cSJim Cownie double dosc = double(other.sampleCount);
1104cc4bb4cSJim Cownie double delta = other.meanVal - meanVal;
1114cc4bb4cSJim Cownie
1123041982dSJonathan Peyton // Try to order these calculations to avoid overflows. If this were Fortran,
1133041982dSJonathan Peyton // then the compiler would not be able to re-order over brackets. In C++ it
1143041982dSJonathan Peyton // may be legal to do that (we certainly hope it doesn't, and CC+ Programming
1153041982dSJonathan Peyton // Language 2nd edition suggests it shouldn't, since it says that exploitation
1163041982dSJonathan Peyton // of associativity can only be made if the operation really is associative
1173041982dSJonathan Peyton // (which floating addition isn't...)).
1184cc4bb4cSJim Cownie meanVal = meanVal * dscBydnsc + other.meanVal * (1 - dscBydnsc);
1194cc4bb4cSJim Cownie m2 = m2 + other.m2 + dscBydnsc * dosc * delta * delta;
1204cc4bb4cSJim Cownie minVal = std::min(minVal, other.minVal);
1214cc4bb4cSJim Cownie maxVal = std::max(maxVal, other.maxVal);
1224cc4bb4cSJim Cownie sampleCount = newSampleCount;
123f0682ac4SJonathan Peyton if (collectingHist)
124f0682ac4SJonathan Peyton hist += other.hist;
1254cc4bb4cSJim Cownie
1264cc4bb4cSJim Cownie return *this;
1274cc4bb4cSJim Cownie }
1284cc4bb4cSJim Cownie
scale(double factor)1293041982dSJonathan Peyton void statistic::scale(double factor) {
1304cc4bb4cSJim Cownie minVal = minVal * factor;
1314cc4bb4cSJim Cownie maxVal = maxVal * factor;
1324cc4bb4cSJim Cownie meanVal = meanVal * factor;
1334cc4bb4cSJim Cownie m2 = m2 * factor * factor;
1344cc4bb4cSJim Cownie return;
1354cc4bb4cSJim Cownie }
1364cc4bb4cSJim Cownie
format(char unit,bool total) const1373041982dSJonathan Peyton std::string statistic::format(char unit, bool total) const {
1386b316febSTerry Wilmarth std::string result = formatSI((double)sampleCount, 9, ' ');
1394cc4bb4cSJim Cownie
1403041982dSJonathan Peyton if (sampleCount == 0) {
141c1a7c97cSJonathan Peyton result = result + std::string(", ") + formatSI(0.0, 9, unit);
142c1a7c97cSJonathan Peyton result = result + std::string(", ") + formatSI(0.0, 9, unit);
143c1a7c97cSJonathan Peyton result = result + std::string(", ") + formatSI(0.0, 9, unit);
144c1a7c97cSJonathan Peyton if (total)
145c1a7c97cSJonathan Peyton result = result + std::string(", ") + formatSI(0.0, 9, unit);
146c1a7c97cSJonathan Peyton result = result + std::string(", ") + formatSI(0.0, 9, unit);
1473041982dSJonathan Peyton } else {
1484cc4bb4cSJim Cownie result = result + std::string(", ") + formatSI(minVal, 9, unit);
1494cc4bb4cSJim Cownie result = result + std::string(", ") + formatSI(meanVal, 9, unit);
1504cc4bb4cSJim Cownie result = result + std::string(", ") + formatSI(maxVal, 9, unit);
1514cc4bb4cSJim Cownie if (total)
1523041982dSJonathan Peyton result =
1533041982dSJonathan Peyton result + std::string(", ") + formatSI(meanVal * sampleCount, 9, unit);
1544cc4bb4cSJim Cownie result = result + std::string(", ") + formatSI(getSD(), 9, unit);
155c1a7c97cSJonathan Peyton }
1564cc4bb4cSJim Cownie return result;
1574cc4bb4cSJim Cownie }
1584cc4bb4cSJim Cownie
159f0682ac4SJonathan Peyton /* ************* histogram member functions ************* */
160f0682ac4SJonathan Peyton
161f0682ac4SJonathan Peyton // Lowest bin that has anything in it
minBin() const162f0682ac4SJonathan Peyton int logHistogram::minBin() const {
163f0682ac4SJonathan Peyton for (int i = 0; i < numBins; i++) {
164f0682ac4SJonathan Peyton if (bins[i].count != 0)
165f0682ac4SJonathan Peyton return i - logOffset;
166f0682ac4SJonathan Peyton }
167f0682ac4SJonathan Peyton return -logOffset;
168f0682ac4SJonathan Peyton }
169f0682ac4SJonathan Peyton
170f0682ac4SJonathan Peyton // Highest bin that has anything in it
maxBin() const171f0682ac4SJonathan Peyton int logHistogram::maxBin() const {
172f0682ac4SJonathan Peyton for (int i = numBins - 1; i >= 0; i--) {
173f0682ac4SJonathan Peyton if (bins[i].count != 0)
174f0682ac4SJonathan Peyton return i - logOffset;
175f0682ac4SJonathan Peyton }
176f0682ac4SJonathan Peyton return -logOffset;
177f0682ac4SJonathan Peyton }
178f0682ac4SJonathan Peyton
179f0682ac4SJonathan Peyton // Which bin does this sample belong in ?
findBin(double sample)180f0682ac4SJonathan Peyton uint32_t logHistogram::findBin(double sample) {
181f0682ac4SJonathan Peyton double v = std::fabs(sample);
182f0682ac4SJonathan Peyton // Simply loop up looking which bin to put it in.
183f0682ac4SJonathan Peyton // According to a micro-architect this is likely to be faster than a binary
184f0682ac4SJonathan Peyton // search, since
185f0682ac4SJonathan Peyton // it will only have one branch mis-predict
1866b316febSTerry Wilmarth for (int b = 0; b < numBins - 1; b++)
187f0682ac4SJonathan Peyton if (binMax[b] > v)
188f0682ac4SJonathan Peyton return b;
1896b316febSTerry Wilmarth return numBins - 1;
190f0682ac4SJonathan Peyton }
191f0682ac4SJonathan Peyton
addSample(double sample)192f0682ac4SJonathan Peyton void logHistogram::addSample(double sample) {
193f0682ac4SJonathan Peyton if (sample == 0.0) {
194f0682ac4SJonathan Peyton zeroCount += 1;
195f0682ac4SJonathan Peyton #ifdef KMP_DEBUG
196f0682ac4SJonathan Peyton _total++;
197f0682ac4SJonathan Peyton check();
198f0682ac4SJonathan Peyton #endif
199f0682ac4SJonathan Peyton return;
200f0682ac4SJonathan Peyton }
201f0682ac4SJonathan Peyton KMP_DEBUG_ASSERT(std::isfinite(sample));
202f0682ac4SJonathan Peyton uint32_t bin = findBin(sample);
203f0682ac4SJonathan Peyton KMP_DEBUG_ASSERT(0 <= bin && bin < numBins);
204f0682ac4SJonathan Peyton
205f0682ac4SJonathan Peyton bins[bin].count += 1;
206f0682ac4SJonathan Peyton bins[bin].total += sample;
207f0682ac4SJonathan Peyton #ifdef KMP_DEBUG
208f0682ac4SJonathan Peyton _total++;
209f0682ac4SJonathan Peyton check();
210f0682ac4SJonathan Peyton #endif
211f0682ac4SJonathan Peyton }
212f0682ac4SJonathan Peyton
213f0682ac4SJonathan Peyton // This may not be the format we want, but it'll do for now
format(char unit) const214f0682ac4SJonathan Peyton std::string logHistogram::format(char unit) const {
215f0682ac4SJonathan Peyton std::stringstream result;
216f0682ac4SJonathan Peyton
217f0682ac4SJonathan Peyton result << "Bin, Count, Total\n";
218f0682ac4SJonathan Peyton if (zeroCount) {
219f0682ac4SJonathan Peyton result << "0, " << formatSI(zeroCount, 9, ' ') << ", ",
220f0682ac4SJonathan Peyton formatSI(0.0, 9, unit);
221f0682ac4SJonathan Peyton if (count(minBin()) == 0)
222f0682ac4SJonathan Peyton return result.str();
223f0682ac4SJonathan Peyton result << "\n";
224f0682ac4SJonathan Peyton }
225f0682ac4SJonathan Peyton for (int i = minBin(); i <= maxBin(); i++) {
2266b316febSTerry Wilmarth result << "10**" << i << "<=v<";
2276b316febSTerry Wilmarth if (i + 1 == numBins - 1)
2286b316febSTerry Wilmarth result << "infinity, ";
2296b316febSTerry Wilmarth else
2306b316febSTerry Wilmarth result << "10**" << (i + 1) << ", ";
2316b316febSTerry Wilmarth result << formatSI(count(i), 9, ' ') << ", " << formatSI(total(i), 9, unit);
232f0682ac4SJonathan Peyton if (i != maxBin())
233f0682ac4SJonathan Peyton result << "\n";
234f0682ac4SJonathan Peyton }
235f0682ac4SJonathan Peyton
236f0682ac4SJonathan Peyton return result.str();
237f0682ac4SJonathan Peyton }
238f0682ac4SJonathan Peyton
2394cc4bb4cSJim Cownie /* ************* explicitTimer member functions ************* */
2404cc4bb4cSJim Cownie
start(tsc_tick_count tick)241f0682ac4SJonathan Peyton void explicitTimer::start(tsc_tick_count tick) {
242f0682ac4SJonathan Peyton startTime = tick;
24311dc82faSJonathan Peyton totalPauseTime = 0;
2444cc4bb4cSJim Cownie if (timeStat::logEvent(timerEnumValue)) {
2454cc4bb4cSJim Cownie __kmp_stats_thread_ptr->incrementNestValue();
2464cc4bb4cSJim Cownie }
2474cc4bb4cSJim Cownie return;
2484cc4bb4cSJim Cownie }
2494cc4bb4cSJim Cownie
stop(tsc_tick_count tick,kmp_stats_list * stats_ptr)250f0682ac4SJonathan Peyton void explicitTimer::stop(tsc_tick_count tick,
2513041982dSJonathan Peyton kmp_stats_list *stats_ptr /* = nullptr */) {
2524cc4bb4cSJim Cownie if (startTime.getValue() == 0)
2534cc4bb4cSJim Cownie return;
2544cc4bb4cSJim Cownie
255f0682ac4SJonathan Peyton stat->addSample(((tick - startTime) - totalPauseTime).ticks());
2564cc4bb4cSJim Cownie
2574cc4bb4cSJim Cownie if (timeStat::logEvent(timerEnumValue)) {
2585375fe82SJonathan Peyton if (!stats_ptr)
2595375fe82SJonathan Peyton stats_ptr = __kmp_stats_thread_ptr;
2603041982dSJonathan Peyton stats_ptr->push_event(
2613041982dSJonathan Peyton startTime.getValue() - __kmp_stats_start_time.getValue(),
262f0682ac4SJonathan Peyton tick.getValue() - __kmp_stats_start_time.getValue(),
2633041982dSJonathan Peyton __kmp_stats_thread_ptr->getNestValue(), timerEnumValue);
2645375fe82SJonathan Peyton stats_ptr->decrementNestValue();
2654cc4bb4cSJim Cownie }
2664cc4bb4cSJim Cownie
2673041982dSJonathan Peyton /* We accept the risk that we drop a sample because it really did start at
2683041982dSJonathan Peyton t==0. */
2694cc4bb4cSJim Cownie startTime = 0;
2704cc4bb4cSJim Cownie return;
2714cc4bb4cSJim Cownie }
2724cc4bb4cSJim Cownie
27311dc82faSJonathan Peyton /* ************* partitionedTimers member functions ************* */
partitionedTimers()2743041982dSJonathan Peyton partitionedTimers::partitionedTimers() { timer_stack.reserve(8); }
27511dc82faSJonathan Peyton
27642016791SKazuaki Ishizaki // initialize the partitioned timers to an initial timer
init(explicitTimer timer)277f0682ac4SJonathan Peyton void partitionedTimers::init(explicitTimer timer) {
27811dc82faSJonathan Peyton KMP_DEBUG_ASSERT(this->timer_stack.size() == 0);
279f0682ac4SJonathan Peyton timer_stack.push_back(timer);
280f0682ac4SJonathan Peyton timer_stack.back().start(tsc_tick_count::now());
28111dc82faSJonathan Peyton }
28211dc82faSJonathan Peyton
28311dc82faSJonathan Peyton // stop/save the current timer, and start the new timer (timer_pair)
28411dc82faSJonathan Peyton // There is a special condition where if the current timer is equal to
28511dc82faSJonathan Peyton // the one you are trying to push, then it only manipulates the stack,
28611dc82faSJonathan Peyton // and it won't stop/start the currently running timer.
push(explicitTimer timer)287f0682ac4SJonathan Peyton void partitionedTimers::push(explicitTimer timer) {
28811dc82faSJonathan Peyton // get the current timer
289f0682ac4SJonathan Peyton // pause current timer
29011dc82faSJonathan Peyton // push new timer
29111dc82faSJonathan Peyton // start the new timer
292f0682ac4SJonathan Peyton explicitTimer *current_timer, *new_timer;
293f0682ac4SJonathan Peyton size_t stack_size;
29411dc82faSJonathan Peyton KMP_DEBUG_ASSERT(this->timer_stack.size() > 0);
295f0682ac4SJonathan Peyton timer_stack.push_back(timer);
296f0682ac4SJonathan Peyton stack_size = timer_stack.size();
297f0682ac4SJonathan Peyton current_timer = &(timer_stack[stack_size - 2]);
298f0682ac4SJonathan Peyton new_timer = &(timer_stack[stack_size - 1]);
299f0682ac4SJonathan Peyton tsc_tick_count tick = tsc_tick_count::now();
300f0682ac4SJonathan Peyton current_timer->pause(tick);
301f0682ac4SJonathan Peyton new_timer->start(tick);
30211dc82faSJonathan Peyton }
30311dc82faSJonathan Peyton
30411dc82faSJonathan Peyton // stop/discard the current timer, and start the previously saved timer
pop()30511dc82faSJonathan Peyton void partitionedTimers::pop() {
30611dc82faSJonathan Peyton // get the current timer
307f0682ac4SJonathan Peyton // stop current timer (record event/sample)
30811dc82faSJonathan Peyton // pop current timer
309f0682ac4SJonathan Peyton // get the new current timer and resume
310f0682ac4SJonathan Peyton explicitTimer *old_timer, *new_timer;
311f0682ac4SJonathan Peyton size_t stack_size = timer_stack.size();
312f0682ac4SJonathan Peyton KMP_DEBUG_ASSERT(stack_size > 1);
313f0682ac4SJonathan Peyton old_timer = &(timer_stack[stack_size - 1]);
314f0682ac4SJonathan Peyton new_timer = &(timer_stack[stack_size - 2]);
315f0682ac4SJonathan Peyton tsc_tick_count tick = tsc_tick_count::now();
316f0682ac4SJonathan Peyton old_timer->stop(tick);
317f0682ac4SJonathan Peyton new_timer->resume(tick);
31811dc82faSJonathan Peyton timer_stack.pop_back();
31911dc82faSJonathan Peyton }
320f0682ac4SJonathan Peyton
exchange(explicitTimer timer)321f0682ac4SJonathan Peyton void partitionedTimers::exchange(explicitTimer timer) {
322f0682ac4SJonathan Peyton // get the current timer
323f0682ac4SJonathan Peyton // stop current timer (record event/sample)
324f0682ac4SJonathan Peyton // push new timer
325f0682ac4SJonathan Peyton // start the new timer
326f0682ac4SJonathan Peyton explicitTimer *current_timer, *new_timer;
327f0682ac4SJonathan Peyton size_t stack_size;
328f0682ac4SJonathan Peyton KMP_DEBUG_ASSERT(this->timer_stack.size() > 0);
329f0682ac4SJonathan Peyton tsc_tick_count tick = tsc_tick_count::now();
330f0682ac4SJonathan Peyton stack_size = timer_stack.size();
331f0682ac4SJonathan Peyton current_timer = &(timer_stack[stack_size - 1]);
332f0682ac4SJonathan Peyton current_timer->stop(tick);
333f0682ac4SJonathan Peyton timer_stack.pop_back();
334f0682ac4SJonathan Peyton timer_stack.push_back(timer);
335f0682ac4SJonathan Peyton new_timer = &(timer_stack[stack_size - 1]);
336f0682ac4SJonathan Peyton new_timer->start(tick);
33711dc82faSJonathan Peyton }
33811dc82faSJonathan Peyton
33911dc82faSJonathan Peyton // Wind up all the currently running timers.
34011dc82faSJonathan Peyton // This pops off all the timers from the stack and clears the stack
34111dc82faSJonathan Peyton // After this is called, init() must be run again to initialize the
34211dc82faSJonathan Peyton // stack of timers
windup()34311dc82faSJonathan Peyton void partitionedTimers::windup() {
34411dc82faSJonathan Peyton while (timer_stack.size() > 1) {
34511dc82faSJonathan Peyton this->pop();
34611dc82faSJonathan Peyton }
347f0682ac4SJonathan Peyton // Pop the timer from the init() call
34811dc82faSJonathan Peyton if (timer_stack.size() > 0) {
349f0682ac4SJonathan Peyton timer_stack.back().stop(tsc_tick_count::now());
35011dc82faSJonathan Peyton timer_stack.pop_back();
35111dc82faSJonathan Peyton }
35211dc82faSJonathan Peyton }
35311dc82faSJonathan Peyton
3544cc4bb4cSJim Cownie /* ************* kmp_stats_event_vector member functions ************* */
3554cc4bb4cSJim Cownie
deallocate()3564cc4bb4cSJim Cownie void kmp_stats_event_vector::deallocate() {
3574cc4bb4cSJim Cownie __kmp_free(events);
3584cc4bb4cSJim Cownie internal_size = 0;
3594cc4bb4cSJim Cownie allocated_size = 0;
3604cc4bb4cSJim Cownie events = NULL;
3614cc4bb4cSJim Cownie }
3624cc4bb4cSJim Cownie
3634cc4bb4cSJim Cownie // This function is for qsort() which requires the compare function to return
3643041982dSJonathan Peyton // either a negative number if event1 < event2, a positive number if event1 >
3653041982dSJonathan Peyton // event2 or zero if event1 == event2. This sorts by start time (lowest to
3663041982dSJonathan Peyton // highest).
compare_two_events(const void * event1,const void * event2)3674cc4bb4cSJim Cownie int compare_two_events(const void *event1, const void *event2) {
368f0682ac4SJonathan Peyton const kmp_stats_event *ev1 = RCAST(const kmp_stats_event *, event1);
369f0682ac4SJonathan Peyton const kmp_stats_event *ev2 = RCAST(const kmp_stats_event *, event2);
3704cc4bb4cSJim Cownie
3713041982dSJonathan Peyton if (ev1->getStart() < ev2->getStart())
3723041982dSJonathan Peyton return -1;
3733041982dSJonathan Peyton else if (ev1->getStart() > ev2->getStart())
3743041982dSJonathan Peyton return 1;
3753041982dSJonathan Peyton else
3763041982dSJonathan Peyton return 0;
3774cc4bb4cSJim Cownie }
3784cc4bb4cSJim Cownie
sort()3794cc4bb4cSJim Cownie void kmp_stats_event_vector::sort() {
3804cc4bb4cSJim Cownie qsort(events, internal_size, sizeof(kmp_stats_event), compare_two_events);
3814cc4bb4cSJim Cownie }
3824cc4bb4cSJim Cownie
3834cc4bb4cSJim Cownie /* ************* kmp_stats_list member functions ************* */
3844cc4bb4cSJim Cownie
3854cc4bb4cSJim Cownie // returns a pointer to newly created stats node
push_back(int gtid)3864cc4bb4cSJim Cownie kmp_stats_list *kmp_stats_list::push_back(int gtid) {
3873041982dSJonathan Peyton kmp_stats_list *newnode =
3883041982dSJonathan Peyton (kmp_stats_list *)__kmp_allocate(sizeof(kmp_stats_list));
3893041982dSJonathan Peyton // placement new, only requires space and pointer and initializes (so
3903041982dSJonathan Peyton // __kmp_allocate instead of C++ new[] is used)
3914cc4bb4cSJim Cownie new (newnode) kmp_stats_list();
3924cc4bb4cSJim Cownie newnode->setGtid(gtid);
3934cc4bb4cSJim Cownie newnode->prev = this->prev;
3944cc4bb4cSJim Cownie newnode->next = this;
3954cc4bb4cSJim Cownie newnode->prev->next = newnode;
3964cc4bb4cSJim Cownie newnode->next->prev = newnode;
3974cc4bb4cSJim Cownie return newnode;
3984cc4bb4cSJim Cownie }
deallocate()3994cc4bb4cSJim Cownie void kmp_stats_list::deallocate() {
4004cc4bb4cSJim Cownie kmp_stats_list *ptr = this->next;
4014cc4bb4cSJim Cownie kmp_stats_list *delptr = this->next;
4024cc4bb4cSJim Cownie while (ptr != this) {
4034cc4bb4cSJim Cownie delptr = ptr;
4044cc4bb4cSJim Cownie ptr = ptr->next;
4054cc4bb4cSJim Cownie // placement new means we have to explicitly call destructor.
4064cc4bb4cSJim Cownie delptr->_event_vector.deallocate();
4074cc4bb4cSJim Cownie delptr->~kmp_stats_list();
4084cc4bb4cSJim Cownie __kmp_free(delptr);
4094cc4bb4cSJim Cownie }
4104cc4bb4cSJim Cownie }
begin()4114cc4bb4cSJim Cownie kmp_stats_list::iterator kmp_stats_list::begin() {
4124cc4bb4cSJim Cownie kmp_stats_list::iterator it;
4134cc4bb4cSJim Cownie it.ptr = this->next;
4144cc4bb4cSJim Cownie return it;
4154cc4bb4cSJim Cownie }
end()4164cc4bb4cSJim Cownie kmp_stats_list::iterator kmp_stats_list::end() {
4174cc4bb4cSJim Cownie kmp_stats_list::iterator it;
4184cc4bb4cSJim Cownie it.ptr = this;
4194cc4bb4cSJim Cownie return it;
4204cc4bb4cSJim Cownie }
size()4214cc4bb4cSJim Cownie int kmp_stats_list::size() {
4224cc4bb4cSJim Cownie int retval;
4234cc4bb4cSJim Cownie kmp_stats_list::iterator it;
4243041982dSJonathan Peyton for (retval = 0, it = begin(); it != end(); it++, retval++) {
4253041982dSJonathan Peyton }
4264cc4bb4cSJim Cownie return retval;
4274cc4bb4cSJim Cownie }
4284cc4bb4cSJim Cownie
4294cc4bb4cSJim Cownie /* ************* kmp_stats_list::iterator member functions ************* */
4304cc4bb4cSJim Cownie
iterator()4314cc4bb4cSJim Cownie kmp_stats_list::iterator::iterator() : ptr(NULL) {}
~iterator()4324cc4bb4cSJim Cownie kmp_stats_list::iterator::~iterator() {}
operator ++()4334cc4bb4cSJim Cownie kmp_stats_list::iterator kmp_stats_list::iterator::operator++() {
4344cc4bb4cSJim Cownie this->ptr = this->ptr->next;
4354cc4bb4cSJim Cownie return *this;
4364cc4bb4cSJim Cownie }
operator ++(int dummy)4374cc4bb4cSJim Cownie kmp_stats_list::iterator kmp_stats_list::iterator::operator++(int dummy) {
4384cc4bb4cSJim Cownie this->ptr = this->ptr->next;
4394cc4bb4cSJim Cownie return *this;
4404cc4bb4cSJim Cownie }
operator --()4414cc4bb4cSJim Cownie kmp_stats_list::iterator kmp_stats_list::iterator::operator--() {
4424cc4bb4cSJim Cownie this->ptr = this->ptr->prev;
4434cc4bb4cSJim Cownie return *this;
4444cc4bb4cSJim Cownie }
operator --(int dummy)4454cc4bb4cSJim Cownie kmp_stats_list::iterator kmp_stats_list::iterator::operator--(int dummy) {
4464cc4bb4cSJim Cownie this->ptr = this->ptr->prev;
4474cc4bb4cSJim Cownie return *this;
4484cc4bb4cSJim Cownie }
operator !=(const kmp_stats_list::iterator & rhs)4494cc4bb4cSJim Cownie bool kmp_stats_list::iterator::operator!=(const kmp_stats_list::iterator &rhs) {
4504cc4bb4cSJim Cownie return this->ptr != rhs.ptr;
4514cc4bb4cSJim Cownie }
operator ==(const kmp_stats_list::iterator & rhs)4524cc4bb4cSJim Cownie bool kmp_stats_list::iterator::operator==(const kmp_stats_list::iterator &rhs) {
4534cc4bb4cSJim Cownie return this->ptr == rhs.ptr;
4544cc4bb4cSJim Cownie }
operator *() const4554cc4bb4cSJim Cownie kmp_stats_list *kmp_stats_list::iterator::operator*() const {
4564cc4bb4cSJim Cownie return this->ptr;
4574cc4bb4cSJim Cownie }
4584cc4bb4cSJim Cownie
4594cc4bb4cSJim Cownie /* ************* kmp_stats_output_module functions ************** */
4604cc4bb4cSJim Cownie
4614cc4bb4cSJim Cownie const char *kmp_stats_output_module::eventsFileName = NULL;
4624cc4bb4cSJim Cownie const char *kmp_stats_output_module::plotFileName = NULL;
4634cc4bb4cSJim Cownie int kmp_stats_output_module::printPerThreadFlag = 0;
4644cc4bb4cSJim Cownie int kmp_stats_output_module::printPerThreadEventsFlag = 0;
4654cc4bb4cSJim Cownie
lastName(char * name)466f0682ac4SJonathan Peyton static char const *lastName(char *name) {
4676b316febSTerry Wilmarth int l = (int)strlen(name);
468f0682ac4SJonathan Peyton for (int i = l - 1; i >= 0; --i) {
469f0682ac4SJonathan Peyton if (name[i] == '.')
470f0682ac4SJonathan Peyton name[i] = '_';
471f0682ac4SJonathan Peyton if (name[i] == '/')
472f0682ac4SJonathan Peyton return name + i + 1;
473f0682ac4SJonathan Peyton }
474f0682ac4SJonathan Peyton return name;
475f0682ac4SJonathan Peyton }
476f0682ac4SJonathan Peyton
477f0682ac4SJonathan Peyton /* Read the name of the executable from /proc/self/cmdline */
getImageName(char * buffer,size_t buflen)478f0682ac4SJonathan Peyton static char const *getImageName(char *buffer, size_t buflen) {
479f0682ac4SJonathan Peyton FILE *f = fopen("/proc/self/cmdline", "r");
480f0682ac4SJonathan Peyton buffer[0] = char(0);
481f0682ac4SJonathan Peyton if (!f)
482f0682ac4SJonathan Peyton return buffer;
483f0682ac4SJonathan Peyton
484f0682ac4SJonathan Peyton // The file contains char(0) delimited words from the commandline.
485f0682ac4SJonathan Peyton // This just returns the last filename component of the first word on the
486f0682ac4SJonathan Peyton // line.
487f0682ac4SJonathan Peyton size_t n = fread(buffer, 1, buflen, f);
488f0682ac4SJonathan Peyton if (n == 0) {
489f0682ac4SJonathan Peyton fclose(f);
490f0682ac4SJonathan Peyton KMP_CHECK_SYSFAIL("fread", 1)
491f0682ac4SJonathan Peyton }
492f0682ac4SJonathan Peyton fclose(f);
493f0682ac4SJonathan Peyton buffer[buflen - 1] = char(0);
494f0682ac4SJonathan Peyton return lastName(buffer);
495f0682ac4SJonathan Peyton }
496f0682ac4SJonathan Peyton
getTime(char * buffer,size_t buflen,bool underscores=false)497f0682ac4SJonathan Peyton static void getTime(char *buffer, size_t buflen, bool underscores = false) {
498f0682ac4SJonathan Peyton time_t timer;
499f0682ac4SJonathan Peyton
500f0682ac4SJonathan Peyton time(&timer);
501f0682ac4SJonathan Peyton
502f0682ac4SJonathan Peyton struct tm *tm_info = localtime(&timer);
503f0682ac4SJonathan Peyton if (underscores)
504f0682ac4SJonathan Peyton strftime(buffer, buflen, "%Y-%m-%d_%H%M%S", tm_info);
505f0682ac4SJonathan Peyton else
506f0682ac4SJonathan Peyton strftime(buffer, buflen, "%Y-%m-%d %H%M%S", tm_info);
507f0682ac4SJonathan Peyton }
508f0682ac4SJonathan Peyton
509f0682ac4SJonathan Peyton /* Generate a stats file name, expanding prototypes */
generateFilename(char const * prototype,char const * imageName)510f0682ac4SJonathan Peyton static std::string generateFilename(char const *prototype,
511f0682ac4SJonathan Peyton char const *imageName) {
512f0682ac4SJonathan Peyton std::string res;
513f0682ac4SJonathan Peyton
514f0682ac4SJonathan Peyton for (int i = 0; prototype[i] != char(0); i++) {
515f0682ac4SJonathan Peyton char ch = prototype[i];
516f0682ac4SJonathan Peyton
517f0682ac4SJonathan Peyton if (ch == '%') {
518f0682ac4SJonathan Peyton i++;
519f0682ac4SJonathan Peyton if (prototype[i] == char(0))
520f0682ac4SJonathan Peyton break;
521f0682ac4SJonathan Peyton
522f0682ac4SJonathan Peyton switch (prototype[i]) {
523f0682ac4SJonathan Peyton case 't': // Insert time and date
524f0682ac4SJonathan Peyton {
525f0682ac4SJonathan Peyton char date[26];
526f0682ac4SJonathan Peyton getTime(date, sizeof(date), true);
527f0682ac4SJonathan Peyton res += date;
528f0682ac4SJonathan Peyton } break;
529f0682ac4SJonathan Peyton case 'e': // Insert executable name
530f0682ac4SJonathan Peyton res += imageName;
531f0682ac4SJonathan Peyton break;
532f0682ac4SJonathan Peyton case 'p': // Insert pid
533f0682ac4SJonathan Peyton {
534f0682ac4SJonathan Peyton std::stringstream ss;
535f0682ac4SJonathan Peyton ss << getpid();
536f0682ac4SJonathan Peyton res += ss.str();
537f0682ac4SJonathan Peyton } break;
538f0682ac4SJonathan Peyton default:
539f0682ac4SJonathan Peyton res += prototype[i];
540f0682ac4SJonathan Peyton break;
541f0682ac4SJonathan Peyton }
542f0682ac4SJonathan Peyton } else
543f0682ac4SJonathan Peyton res += ch;
544f0682ac4SJonathan Peyton }
545f0682ac4SJonathan Peyton return res;
546f0682ac4SJonathan Peyton }
547f0682ac4SJonathan Peyton
5483041982dSJonathan Peyton // init() is called very near the beginning of execution time in the constructor
5493041982dSJonathan Peyton // of __kmp_stats_global_output
init()5503041982dSJonathan Peyton void kmp_stats_output_module::init() {
551f0682ac4SJonathan Peyton
5524cc4bb4cSJim Cownie char *statsFileName = getenv("KMP_STATS_FILE");
5534cc4bb4cSJim Cownie eventsFileName = getenv("KMP_STATS_EVENTS_FILE");
5544cc4bb4cSJim Cownie plotFileName = getenv("KMP_STATS_PLOT_FILE");
5554cc4bb4cSJim Cownie char *threadStats = getenv("KMP_STATS_THREADS");
5564cc4bb4cSJim Cownie char *threadEvents = getenv("KMP_STATS_EVENTS");
5574cc4bb4cSJim Cownie
5584cc4bb4cSJim Cownie // set the stats output filenames based on environment variables and defaults
55998b76f6fSJonathan Peyton if (statsFileName) {
560f0682ac4SJonathan Peyton char imageName[1024];
561f0682ac4SJonathan Peyton // Process any escapes (e.g., %p, %e, %t) in the name
562f0682ac4SJonathan Peyton outputFileName = generateFilename(
563f0682ac4SJonathan Peyton statsFileName, getImageName(&imageName[0], sizeof(imageName)));
56498b76f6fSJonathan Peyton }
5654cc4bb4cSJim Cownie eventsFileName = eventsFileName ? eventsFileName : "events.dat";
5664cc4bb4cSJim Cownie plotFileName = plotFileName ? plotFileName : "events.plt";
5674cc4bb4cSJim Cownie
5683041982dSJonathan Peyton // set the flags based on environment variables matching: true, on, 1, .true.
5693041982dSJonathan Peyton // , .t. , yes
5704cc4bb4cSJim Cownie printPerThreadFlag = __kmp_str_match_true(threadStats);
5714cc4bb4cSJim Cownie printPerThreadEventsFlag = __kmp_str_match_true(threadEvents);
5724cc4bb4cSJim Cownie
5734cc4bb4cSJim Cownie if (printPerThreadEventsFlag) {
5744cc4bb4cSJim Cownie // assigns a color to each timer for printing
5754cc4bb4cSJim Cownie setupEventColors();
5764cc4bb4cSJim Cownie } else {
5774cc4bb4cSJim Cownie // will clear flag so that no event will be logged
5784cc4bb4cSJim Cownie timeStat::clearEventFlags();
5794cc4bb4cSJim Cownie }
5804cc4bb4cSJim Cownie }
5814cc4bb4cSJim Cownie
setupEventColors()5824cc4bb4cSJim Cownie void kmp_stats_output_module::setupEventColors() {
5834cc4bb4cSJim Cownie int i;
5844cc4bb4cSJim Cownie int globalColorIndex = 0;
5854cc4bb4cSJim Cownie int numGlobalColors = sizeof(globalColorArray) / sizeof(rgb_color);
5864cc4bb4cSJim Cownie for (i = 0; i < TIMER_LAST; i++) {
5874cc4bb4cSJim Cownie if (timeStat::logEvent((timer_e)i)) {
5884cc4bb4cSJim Cownie timerColorInfo[i] = globalColorArray[globalColorIndex];
5894cc4bb4cSJim Cownie globalColorIndex = (globalColorIndex + 1) % numGlobalColors;
5904cc4bb4cSJim Cownie }
5914cc4bb4cSJim Cownie }
5924cc4bb4cSJim Cownie }
5934cc4bb4cSJim Cownie
printTimerStats(FILE * statsOut,statistic const * theStats,statistic const * totalStats)5943041982dSJonathan Peyton void kmp_stats_output_module::printTimerStats(FILE *statsOut,
5953041982dSJonathan Peyton statistic const *theStats,
5963041982dSJonathan Peyton statistic const *totalStats) {
597f0682ac4SJonathan Peyton fprintf(statsOut,
598f0682ac4SJonathan Peyton "Timer, SampleCount, Min, "
5993041982dSJonathan Peyton "Mean, Max, Total, SD\n");
6006e98d798SJonathan Peyton for (timer_e s = timer_e(0); s < TIMER_LAST; s = timer_e(s + 1)) {
6014cc4bb4cSJim Cownie statistic const *stat = &theStats[s];
6026e98d798SJonathan Peyton char tag = timeStat::noUnits(s) ? ' ' : 'T';
603e2554af8SJonathan Peyton
604f0682ac4SJonathan Peyton fprintf(statsOut, "%-35s, %s\n", timeStat::name(s),
6053041982dSJonathan Peyton stat->format(tag, true).c_str());
60653eca521SJonathan Peyton }
607e2554af8SJonathan Peyton // Also print the Total_ versions of times.
60853eca521SJonathan Peyton for (timer_e s = timer_e(0); s < TIMER_LAST; s = timer_e(s + 1)) {
60953eca521SJonathan Peyton char tag = timeStat::noUnits(s) ? ' ' : 'T';
6106e98d798SJonathan Peyton if (totalStats && !timeStat::noTotal(s))
611f0682ac4SJonathan Peyton fprintf(statsOut, "Total_%-29s, %s\n", timeStat::name(s),
6123041982dSJonathan Peyton totalStats[s].format(tag, true).c_str());
6134cc4bb4cSJim Cownie }
614f0682ac4SJonathan Peyton
61542016791SKazuaki Ishizaki // Print histogram of statistics
616f0682ac4SJonathan Peyton if (theStats[0].haveHist()) {
617f0682ac4SJonathan Peyton fprintf(statsOut, "\nTimer distributions\n");
618f0682ac4SJonathan Peyton for (int s = 0; s < TIMER_LAST; s++) {
619f0682ac4SJonathan Peyton statistic const *stat = &theStats[s];
620f0682ac4SJonathan Peyton
621f0682ac4SJonathan Peyton if (stat->getCount() != 0) {
622f0682ac4SJonathan Peyton char tag = timeStat::noUnits(timer_e(s)) ? ' ' : 'T';
623f0682ac4SJonathan Peyton
624f0682ac4SJonathan Peyton fprintf(statsOut, "%s\n", timeStat::name(timer_e(s)));
625f0682ac4SJonathan Peyton fprintf(statsOut, "%s\n", stat->getHist()->format(tag).c_str());
626f0682ac4SJonathan Peyton }
627f0682ac4SJonathan Peyton }
628f0682ac4SJonathan Peyton }
629e2554af8SJonathan Peyton }
630e2554af8SJonathan Peyton
printCounterStats(FILE * statsOut,statistic const * theStats)6313041982dSJonathan Peyton void kmp_stats_output_module::printCounterStats(FILE *statsOut,
6323041982dSJonathan Peyton statistic const *theStats) {
6333041982dSJonathan Peyton fprintf(statsOut, "Counter, ThreadCount, Min, Mean, "
6343041982dSJonathan Peyton " Max, Total, SD\n");
6354cc4bb4cSJim Cownie for (int s = 0; s < COUNTER_LAST; s++) {
6364cc4bb4cSJim Cownie statistic const *stat = &theStats[s];
6373041982dSJonathan Peyton fprintf(statsOut, "%-25s, %s\n", counter::name(counter_e(s)),
6383041982dSJonathan Peyton stat->format(' ', true).c_str());
6394cc4bb4cSJim Cownie }
640f0682ac4SJonathan Peyton // Print histogram of counters
641f0682ac4SJonathan Peyton if (theStats[0].haveHist()) {
642f0682ac4SJonathan Peyton fprintf(statsOut, "\nCounter distributions\n");
643f0682ac4SJonathan Peyton for (int s = 0; s < COUNTER_LAST; s++) {
644f0682ac4SJonathan Peyton statistic const *stat = &theStats[s];
645f0682ac4SJonathan Peyton
646f0682ac4SJonathan Peyton if (stat->getCount() != 0) {
647f0682ac4SJonathan Peyton fprintf(statsOut, "%s\n", counter::name(counter_e(s)));
648f0682ac4SJonathan Peyton fprintf(statsOut, "%s\n", stat->getHist()->format(' ').c_str());
649f0682ac4SJonathan Peyton }
650f0682ac4SJonathan Peyton }
651f0682ac4SJonathan Peyton }
6524cc4bb4cSJim Cownie }
6534cc4bb4cSJim Cownie
printCounters(FILE * statsOut,counter const * theCounters)6543041982dSJonathan Peyton void kmp_stats_output_module::printCounters(FILE *statsOut,
6553041982dSJonathan Peyton counter const *theCounters) {
6564cc4bb4cSJim Cownie // We print all the counters even if they are zero.
6574cc4bb4cSJim Cownie // That makes it easier to slice them into a spreadsheet if you need to.
6584cc4bb4cSJim Cownie fprintf(statsOut, "\nCounter, Count\n");
6594cc4bb4cSJim Cownie for (int c = 0; c < COUNTER_LAST; c++) {
6604cc4bb4cSJim Cownie counter const *stat = &theCounters[c];
6613041982dSJonathan Peyton fprintf(statsOut, "%-25s, %s\n", counter::name(counter_e(c)),
6626b316febSTerry Wilmarth formatSI((double)stat->getValue(), 9, ' ').c_str());
6634cc4bb4cSJim Cownie }
6644cc4bb4cSJim Cownie }
6654cc4bb4cSJim Cownie
printEvents(FILE * eventsOut,kmp_stats_event_vector * theEvents,int gtid)6663041982dSJonathan Peyton void kmp_stats_output_module::printEvents(FILE *eventsOut,
6673041982dSJonathan Peyton kmp_stats_event_vector *theEvents,
6683041982dSJonathan Peyton int gtid) {
6694cc4bb4cSJim Cownie // sort by start time before printing
6704cc4bb4cSJim Cownie theEvents->sort();
6714cc4bb4cSJim Cownie for (int i = 0; i < theEvents->size(); i++) {
6724cc4bb4cSJim Cownie kmp_stats_event ev = theEvents->at(i);
6734cc4bb4cSJim Cownie rgb_color color = getEventColor(ev.getTimerName());
674529e0d2eSJonathan Peyton fprintf(eventsOut, "%d %llu %llu %1.1f rgb(%1.1f,%1.1f,%1.1f) %s\n", gtid,
675529e0d2eSJonathan Peyton static_cast<unsigned long long>(ev.getStart()),
676529e0d2eSJonathan Peyton static_cast<unsigned long long>(ev.getStop()),
677529e0d2eSJonathan Peyton 1.2 - (ev.getNestLevel() * 0.2), color.r, color.g, color.b,
678529e0d2eSJonathan Peyton timeStat::name(ev.getTimerName()));
6794cc4bb4cSJim Cownie }
6804cc4bb4cSJim Cownie return;
6814cc4bb4cSJim Cownie }
6824cc4bb4cSJim Cownie
windupExplicitTimers()6833041982dSJonathan Peyton void kmp_stats_output_module::windupExplicitTimers() {
6843041982dSJonathan Peyton // Wind up any explicit timers. We assume that it's fair at this point to just
6854c6a098aSKazuaki Ishizaki // walk all the explicit timers in all threads and say "it's over".
6864cc4bb4cSJim Cownie // If the timer wasn't running, this won't record anything anyway.
6874cc4bb4cSJim Cownie kmp_stats_list::iterator it;
6885375fe82SJonathan Peyton for (it = __kmp_stats_list->begin(); it != __kmp_stats_list->end(); it++) {
68911dc82faSJonathan Peyton kmp_stats_list *ptr = *it;
69011dc82faSJonathan Peyton ptr->getPartitionedTimers()->windup();
691f0682ac4SJonathan Peyton ptr->endLife();
6924cc4bb4cSJim Cownie }
6934cc4bb4cSJim Cownie }
6944cc4bb4cSJim Cownie
printPloticusFile()6954cc4bb4cSJim Cownie void kmp_stats_output_module::printPloticusFile() {
6964cc4bb4cSJim Cownie int i;
6975375fe82SJonathan Peyton int size = __kmp_stats_list->size();
6985aafdd7bSPeyton, Jonathan L kmp_safe_raii_file_t plotOut(plotFileName, "w+");
6994cc4bb4cSJim Cownie fprintf(plotOut, "#proc page\n"
7004cc4bb4cSJim Cownie " pagesize: 15 10\n"
7014cc4bb4cSJim Cownie " scale: 1.0\n\n");
7024cc4bb4cSJim Cownie
703309b00a4SShilei Tian fprintf(plotOut,
704309b00a4SShilei Tian "#proc getdata\n"
7054cc4bb4cSJim Cownie " file: %s\n\n",
7064cc4bb4cSJim Cownie eventsFileName);
7074cc4bb4cSJim Cownie
708309b00a4SShilei Tian fprintf(plotOut,
709309b00a4SShilei Tian "#proc areadef\n"
7104cc4bb4cSJim Cownie " title: OpenMP Sampling Timeline\n"
7114cc4bb4cSJim Cownie " titledetails: align=center size=16\n"
7124cc4bb4cSJim Cownie " rectangle: 1 1 13 9\n"
7134cc4bb4cSJim Cownie " xautorange: datafield=2,3\n"
7144cc4bb4cSJim Cownie " yautorange: -1 %d\n\n",
7154cc4bb4cSJim Cownie size);
7164cc4bb4cSJim Cownie
7174cc4bb4cSJim Cownie fprintf(plotOut, "#proc xaxis\n"
7184cc4bb4cSJim Cownie " stubs: inc\n"
7194cc4bb4cSJim Cownie " stubdetails: size=12\n"
7204cc4bb4cSJim Cownie " label: Time (ticks)\n"
7214cc4bb4cSJim Cownie " labeldetails: size=14\n\n");
7224cc4bb4cSJim Cownie
723309b00a4SShilei Tian fprintf(plotOut,
724309b00a4SShilei Tian "#proc yaxis\n"
7254cc4bb4cSJim Cownie " stubs: inc 1\n"
7264cc4bb4cSJim Cownie " stubrange: 0 %d\n"
7274cc4bb4cSJim Cownie " stubdetails: size=12\n"
7284cc4bb4cSJim Cownie " label: Thread #\n"
7294cc4bb4cSJim Cownie " labeldetails: size=14\n\n",
7304cc4bb4cSJim Cownie size - 1);
7314cc4bb4cSJim Cownie
7324cc4bb4cSJim Cownie fprintf(plotOut, "#proc bars\n"
7334cc4bb4cSJim Cownie " exactcolorfield: 5\n"
7344cc4bb4cSJim Cownie " axis: x\n"
7354cc4bb4cSJim Cownie " locfield: 1\n"
7364cc4bb4cSJim Cownie " segmentfields: 2 3\n"
7374cc4bb4cSJim Cownie " barwidthfield: 4\n\n");
7384cc4bb4cSJim Cownie
7394cc4bb4cSJim Cownie // create legend entries corresponding to the timer color
7404cc4bb4cSJim Cownie for (i = 0; i < TIMER_LAST; i++) {
7414cc4bb4cSJim Cownie if (timeStat::logEvent((timer_e)i)) {
7424cc4bb4cSJim Cownie rgb_color c = getEventColor((timer_e)i);
743309b00a4SShilei Tian fprintf(plotOut,
744309b00a4SShilei Tian "#proc legendentry\n"
7454cc4bb4cSJim Cownie " sampletype: color\n"
7464cc4bb4cSJim Cownie " label: %s\n"
7474cc4bb4cSJim Cownie " details: rgb(%1.1f,%1.1f,%1.1f)\n\n",
7483041982dSJonathan Peyton timeStat::name((timer_e)i), c.r, c.g, c.b);
7494cc4bb4cSJim Cownie }
7504cc4bb4cSJim Cownie }
7514cc4bb4cSJim Cownie
7524cc4bb4cSJim Cownie fprintf(plotOut, "#proc legend\n"
7534cc4bb4cSJim Cownie " format: down\n"
7544cc4bb4cSJim Cownie " location: max max\n\n");
7554cc4bb4cSJim Cownie return;
7564cc4bb4cSJim Cownie }
7574cc4bb4cSJim Cownie
outputEnvVariable(FILE * statsOut,char const * name)758f0682ac4SJonathan Peyton static void outputEnvVariable(FILE *statsOut, char const *name) {
759f0682ac4SJonathan Peyton char const *value = getenv(name);
760f0682ac4SJonathan Peyton fprintf(statsOut, "# %s = %s\n", name, value ? value : "*unspecified*");
761f0682ac4SJonathan Peyton }
762f0682ac4SJonathan Peyton
7633041982dSJonathan Peyton /* Print some useful information about
7643041982dSJonathan Peyton * the date and time this experiment ran.
7653041982dSJonathan Peyton * the machine on which it ran.
7663041982dSJonathan Peyton We output all of this as stylised comments, though we may decide to parse
7673041982dSJonathan Peyton some of it. */
printHeaderInfo(FILE * statsOut)7683041982dSJonathan Peyton void kmp_stats_output_module::printHeaderInfo(FILE *statsOut) {
7696e98d798SJonathan Peyton std::time_t now = std::time(0);
7706e98d798SJonathan Peyton char buffer[40];
7716e98d798SJonathan Peyton char hostName[80];
7726e98d798SJonathan Peyton
7736e98d798SJonathan Peyton std::strftime(&buffer[0], sizeof(buffer), "%c", std::localtime(&now));
7746e98d798SJonathan Peyton fprintf(statsOut, "# Time of run: %s\n", &buffer[0]);
7756e98d798SJonathan Peyton if (gethostname(&hostName[0], sizeof(hostName)) == 0)
7766e98d798SJonathan Peyton fprintf(statsOut, "# Hostname: %s\n", &hostName[0]);
7776e98d798SJonathan Peyton #if KMP_ARCH_X86 || KMP_ARCH_X86_64
7786e98d798SJonathan Peyton fprintf(statsOut, "# CPU: %s\n", &__kmp_cpuinfo.name[0]);
7793041982dSJonathan Peyton fprintf(statsOut, "# Family: %d, Model: %d, Stepping: %d\n",
7803041982dSJonathan Peyton __kmp_cpuinfo.family, __kmp_cpuinfo.model, __kmp_cpuinfo.stepping);
78120c1e4e6SJonathan Peyton if (__kmp_cpuinfo.frequency == 0)
78220c1e4e6SJonathan Peyton fprintf(statsOut, "# Nominal frequency: Unknown\n");
78320c1e4e6SJonathan Peyton else
7843041982dSJonathan Peyton fprintf(statsOut, "# Nominal frequency: %sz\n",
7853041982dSJonathan Peyton formatSI(double(__kmp_cpuinfo.frequency), 9, 'H').c_str());
786f0682ac4SJonathan Peyton outputEnvVariable(statsOut, "KMP_HW_SUBSET");
787f0682ac4SJonathan Peyton outputEnvVariable(statsOut, "KMP_AFFINITY");
788f0682ac4SJonathan Peyton outputEnvVariable(statsOut, "KMP_BLOCKTIME");
789f0682ac4SJonathan Peyton outputEnvVariable(statsOut, "KMP_LIBRARY");
790f0682ac4SJonathan Peyton fprintf(statsOut, "# Production runtime built " __DATE__ " " __TIME__ "\n");
7916e98d798SJonathan Peyton #endif
7926e98d798SJonathan Peyton }
7936e98d798SJonathan Peyton
outputStats(const char * heading)7943041982dSJonathan Peyton void kmp_stats_output_module::outputStats(const char *heading) {
7956e98d798SJonathan Peyton // Stop all the explicit timers in all threads
7963041982dSJonathan Peyton // Do this before declaring the local statistics because thay have
7973041982dSJonathan Peyton // constructors so will take time to create.
7986e98d798SJonathan Peyton windupExplicitTimers();
7996e98d798SJonathan Peyton
8004cc4bb4cSJim Cownie statistic allStats[TIMER_LAST];
8013041982dSJonathan Peyton statistic totalStats[TIMER_LAST]; /* Synthesized, cross threads versions of
8023041982dSJonathan Peyton normal timer stats */
8034cc4bb4cSJim Cownie statistic allCounters[COUNTER_LAST];
8044cc4bb4cSJim Cownie
8055aafdd7bSPeyton, Jonathan L kmp_safe_raii_file_t statsOut;
8065aafdd7bSPeyton, Jonathan L if (!outputFileName.empty()) {
8075aafdd7bSPeyton, Jonathan L statsOut.open(outputFileName.c_str(), "a+");
8085aafdd7bSPeyton, Jonathan L } else {
8095aafdd7bSPeyton, Jonathan L statsOut.set_stderr();
8105aafdd7bSPeyton, Jonathan L }
8114cc4bb4cSJim Cownie
8125aafdd7bSPeyton, Jonathan L kmp_safe_raii_file_t eventsOut;
8134cc4bb4cSJim Cownie if (eventPrintingEnabled()) {
8145aafdd7bSPeyton, Jonathan L eventsOut.open(eventsFileName, "w+");
8154cc4bb4cSJim Cownie }
8164cc4bb4cSJim Cownie
8176e98d798SJonathan Peyton printHeaderInfo(statsOut);
8184cc4bb4cSJim Cownie fprintf(statsOut, "%s\n", heading);
8194cc4bb4cSJim Cownie // Accumulate across threads.
8204cc4bb4cSJim Cownie kmp_stats_list::iterator it;
8215375fe82SJonathan Peyton for (it = __kmp_stats_list->begin(); it != __kmp_stats_list->end(); it++) {
8224cc4bb4cSJim Cownie int t = (*it)->getGtid();
8234cc4bb4cSJim Cownie // Output per thread stats if requested.
8246e98d798SJonathan Peyton if (printPerThreadFlag) {
8254cc4bb4cSJim Cownie fprintf(statsOut, "Thread %d\n", t);
826e2554af8SJonathan Peyton printTimerStats(statsOut, (*it)->getTimers(), 0);
8274cc4bb4cSJim Cownie printCounters(statsOut, (*it)->getCounters());
8284cc4bb4cSJim Cownie fprintf(statsOut, "\n");
8294cc4bb4cSJim Cownie }
8304cc4bb4cSJim Cownie // Output per thread events if requested.
8314cc4bb4cSJim Cownie if (eventPrintingEnabled()) {
8324cc4bb4cSJim Cownie kmp_stats_event_vector events = (*it)->getEventVector();
8334cc4bb4cSJim Cownie printEvents(eventsOut, &events, t);
8344cc4bb4cSJim Cownie }
8354cc4bb4cSJim Cownie
836e2554af8SJonathan Peyton // Accumulate timers.
8376e98d798SJonathan Peyton for (timer_e s = timer_e(0); s < TIMER_LAST; s = timer_e(s + 1)) {
8384cc4bb4cSJim Cownie // See if we should ignore this timer when aggregating
839*97d000cfStlwilmar if ((timeStat::masterOnly(s) && (t != 0)) || // Timer only valid on
840*97d000cfStlwilmar // primary thread and this thread is worker
8413041982dSJonathan Peyton (timeStat::workerOnly(s) && (t == 0)) // Timer only valid on worker
842*97d000cfStlwilmar // and this thread is the primary thread
8433041982dSJonathan Peyton ) {
8444cc4bb4cSJim Cownie continue;
8454cc4bb4cSJim Cownie }
8464cc4bb4cSJim Cownie
8476e98d798SJonathan Peyton statistic *threadStat = (*it)->getTimer(s);
8484cc4bb4cSJim Cownie allStats[s] += *threadStat;
849e2554af8SJonathan Peyton
8506e98d798SJonathan Peyton // Add Total stats for timers that are valid in more than one thread
8516e98d798SJonathan Peyton if (!timeStat::noTotal(s))
852e2554af8SJonathan Peyton totalStats[s].addSample(threadStat->getTotal());
853e2554af8SJonathan Peyton }
8544cc4bb4cSJim Cownie
855e2554af8SJonathan Peyton // Accumulate counters.
8566e98d798SJonathan Peyton for (counter_e c = counter_e(0); c < COUNTER_LAST; c = counter_e(c + 1)) {
8576e98d798SJonathan Peyton if (counter::masterOnly(c) && t != 0)
8584cc4bb4cSJim Cownie continue;
8596b316febSTerry Wilmarth allCounters[c].addSample((double)(*it)->getCounter(c)->getValue());
8604cc4bb4cSJim Cownie }
8614cc4bb4cSJim Cownie }
8624cc4bb4cSJim Cownie
8634cc4bb4cSJim Cownie if (eventPrintingEnabled()) {
8644cc4bb4cSJim Cownie printPloticusFile();
8654cc4bb4cSJim Cownie }
8664cc4bb4cSJim Cownie
8674cc4bb4cSJim Cownie fprintf(statsOut, "Aggregate for all threads\n");
868e2554af8SJonathan Peyton printTimerStats(statsOut, &allStats[0], &totalStats[0]);
8694cc4bb4cSJim Cownie fprintf(statsOut, "\n");
870e2554af8SJonathan Peyton printCounterStats(statsOut, &allCounters[0]);
8714cc4bb4cSJim Cownie }
8724cc4bb4cSJim Cownie
8734cc4bb4cSJim Cownie /* ************* exported C functions ************** */
8744cc4bb4cSJim Cownie
8753041982dSJonathan Peyton // no name mangling for these functions, we want the c files to be able to get
8763041982dSJonathan Peyton // at these functions
8774cc4bb4cSJim Cownie extern "C" {
8784cc4bb4cSJim Cownie
__kmp_reset_stats()8793041982dSJonathan Peyton void __kmp_reset_stats() {
8804cc4bb4cSJim Cownie kmp_stats_list::iterator it;
8815375fe82SJonathan Peyton for (it = __kmp_stats_list->begin(); it != __kmp_stats_list->end(); it++) {
8824cc4bb4cSJim Cownie timeStat *timers = (*it)->getTimers();
8834cc4bb4cSJim Cownie counter *counters = (*it)->getCounters();
8844cc4bb4cSJim Cownie
8854cc4bb4cSJim Cownie for (int t = 0; t < TIMER_LAST; t++)
8864cc4bb4cSJim Cownie timers[t].reset();
8874cc4bb4cSJim Cownie
8884cc4bb4cSJim Cownie for (int c = 0; c < COUNTER_LAST; c++)
8894cc4bb4cSJim Cownie counters[c].reset();
8904cc4bb4cSJim Cownie
8914cc4bb4cSJim Cownie // reset the event vector so all previous events are "erased"
8924cc4bb4cSJim Cownie (*it)->resetEventVector();
8934cc4bb4cSJim Cownie }
8944cc4bb4cSJim Cownie }
8954cc4bb4cSJim Cownie
8963041982dSJonathan Peyton // This function will reset all stats and stop all threads' explicit timers if
8973041982dSJonathan Peyton // they haven't been stopped already.
__kmp_output_stats(const char * heading)8983041982dSJonathan Peyton void __kmp_output_stats(const char *heading) {
8995375fe82SJonathan Peyton __kmp_stats_global_output->outputStats(heading);
9004cc4bb4cSJim Cownie __kmp_reset_stats();
9014cc4bb4cSJim Cownie }
9024cc4bb4cSJim Cownie
__kmp_accumulate_stats_at_exit(void)9033041982dSJonathan Peyton void __kmp_accumulate_stats_at_exit(void) {
9044cc4bb4cSJim Cownie // Only do this once.
9054cc4bb4cSJim Cownie if (KMP_XCHG_FIXED32(&statsPrinted, 1) != 0)
9064cc4bb4cSJim Cownie return;
9074cc4bb4cSJim Cownie
9084cc4bb4cSJim Cownie __kmp_output_stats("Statistics on exit");
9094cc4bb4cSJim Cownie }
9104cc4bb4cSJim Cownie
__kmp_stats_init(void)9113041982dSJonathan Peyton void __kmp_stats_init(void) {
9125375fe82SJonathan Peyton __kmp_init_tas_lock(&__kmp_stats_lock);
9135375fe82SJonathan Peyton __kmp_stats_start_time = tsc_tick_count::now();
9145375fe82SJonathan Peyton __kmp_stats_global_output = new kmp_stats_output_module();
9155375fe82SJonathan Peyton __kmp_stats_list = new kmp_stats_list();
9165375fe82SJonathan Peyton }
9175375fe82SJonathan Peyton
__kmp_stats_fini(void)9183041982dSJonathan Peyton void __kmp_stats_fini(void) {
9195375fe82SJonathan Peyton __kmp_accumulate_stats_at_exit();
9205375fe82SJonathan Peyton __kmp_stats_list->deallocate();
9215375fe82SJonathan Peyton delete __kmp_stats_global_output;
9225375fe82SJonathan Peyton delete __kmp_stats_list;
9234cc4bb4cSJim Cownie }
9244cc4bb4cSJim Cownie
9254cc4bb4cSJim Cownie } // extern "C"
926