[STATS] Add a total statistics count

This change removes synthesized stats and instead has all timers print out a
total which is the aggregate statistics across threads. This is displayed as
"Total_foo" at the end of program. The stats_flags_e::synthesized flag is
removed and the printStats() function is split into two separate functions:
printTimerStats() which can display the aggregate total and printCounterStats().

Differential Revision: http://reviews.llvm.org/D17869


git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@263290 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jonathan Peyton
2016-03-11 20:20:49 +00:00
parent 9a94fcde13
commit 3d4a12f1c0
2 changed files with 60 additions and 76 deletions
+32 -51
View File
@@ -334,43 +334,29 @@ void kmp_stats_output_module::setupEventColors() {
return;
}
void kmp_stats_output_module::printStats(FILE *statsOut, statistic const * theStats, bool areTimers)
void kmp_stats_output_module::printTimerStats(FILE *statsOut, statistic const * theStats, statistic const * totalStats)
{
if (areTimers)
{
// Check if we have useful timers, since we don't print zero value timers we need to avoid
// printing a header and then no data.
bool haveTimers = false;
for (int s = 0; s<TIMER_LAST; s++)
{
if (theStats[s].getCount() != 0)
{
haveTimers = true;
break;
}
}
if (!haveTimers)
return;
}
fprintf (statsOut, "Timer, SampleCount, Min, Mean, Max, Total, SD\n");
for (int s = 0; s<TIMER_LAST; s++) {
statistic const * stat = &theStats[s];
// Print
const char * title = areTimers ? "Timer, SampleCount," : "Counter, ThreadCount,";
fprintf (statsOut, "%s Min, Mean, Max, Total, SD\n", title);
if (areTimers) {
for (int s = 0; s<TIMER_LAST; s++) {
statistic const * stat = &theStats[s];
if (stat->getCount() != 0) {
char tag = timeStat::noUnits(timer_e(s)) ? ' ' : 'T';
fprintf (statsOut, "%-25s, %s\n", timeStat::name(timer_e(s)), stat->format(tag, true).c_str());
}
}
} else { // Counters
for (int s = 0; s<COUNTER_LAST; s++) {
statistic const * stat = &theStats[s];
fprintf (statsOut, "%-25s, %s\n", counter::name(counter_e(s)), stat->format(' ', true).c_str());
char tag = timeStat::noUnits(timer_e(s)) ? ' ' : 'T';
fprintf (statsOut, "%-28s, %s\n", timeStat::name(timer_e(s)), stat->format(tag, true).c_str());
// Also print the Total_ versions of times.
if (totalStats && tag == 'T' && !timeStat::masterOnly(timer_e(s))) {
fprintf(statsOut, "Total_%-22s, %s\n", timeStat::name(timer_e(s)), totalStats[s].format(tag, true).c_str());
}
}
}
}
void kmp_stats_output_module::printCounterStats(FILE *statsOut, statistic const * theStats)
{
fprintf (statsOut, "Counter, ThreadCount, Min, Mean, Max, Total, SD\n");
for (int s = 0; s<COUNTER_LAST; s++) {
statistic const * stat = &theStats[s];
fprintf (statsOut, "%-25s, %s\n", counter::name(counter_e(s)), stat->format(' ', true).c_str());
}
}
void kmp_stats_output_module::printCounters(FILE * statsOut, counter const * theCounters)
{
@@ -480,6 +466,7 @@ void kmp_stats_output_module::printPloticusFile() {
void kmp_stats_output_module::outputStats(const char* heading)
{
statistic allStats[TIMER_LAST];
statistic totalStats[TIMER_LAST]; /* Synthesized, cross threads versions of normal timer stats */
statistic allCounters[COUNTER_LAST];
// stop all the explicit timers for all threads
@@ -503,7 +490,7 @@ void kmp_stats_output_module::outputStats(const char* heading)
// Output per thread stats if requested.
if (perThreadPrintingEnabled()) {
fprintf (statsOut, "Thread %d\n", t);
printStats(statsOut, (*it)->getTimers(), true);
printTimerStats(statsOut, (*it)->getTimers(), 0);
printCounters(statsOut, (*it)->getCounters());
fprintf(statsOut,"\n");
}
@@ -513,11 +500,11 @@ void kmp_stats_output_module::outputStats(const char* heading)
printEvents(eventsOut, &events, t);
}
// Accumulate timers.
for (int s = 0; s<TIMER_LAST; s++) {
// See if we should ignore this timer when aggregating
if ((timeStat::masterOnly(timer_e(s)) && (t != 0)) || // Timer is only valid on the master and this thread is a worker
(timeStat::workerOnly(timer_e(s)) && (t == 0)) || // Timer is only valid on a worker and this thread is the master
timeStat::synthesized(timer_e(s)) // It's a synthesized stat, so there's no raw data for it.
(timeStat::workerOnly(timer_e(s)) && (t == 0)) // Timer is only valid on a worker and this thread is the master
)
{
continue;
@@ -525,21 +512,15 @@ void kmp_stats_output_module::outputStats(const char* heading)
statistic * threadStat = (*it)->getTimer(timer_e(s));
allStats[s] += *threadStat;
// Add Total stats for all real times (not counts) that are valid in more than one thread
if (!timeStat::noUnits(timer_e(s)) && !timeStat::masterOnly(timer_e(s)))
{
totalStats[s].addSample(threadStat->getTotal());
}
}
// Special handling for synthesized statistics.
// These just have to be coded specially here for now.
// At present we only have a few:
// The total parallel work done in each thread.
// The variance here makes it easy to see load imbalance over the whole program (though, of course,
// it's possible to have a code with awful load balance in every parallel region but perfect load
// balance oever the whole program.)
// The time spent in barriers in each thread.
allStats[TIMER_Total_work].addSample ((*it)->getTimer(TIMER_OMP_work)->getTotal());
// Time in explicit barriers.
allStats[TIMER_Total_barrier].addSample ((*it)->getTimer(TIMER_OMP_barrier)->getTotal());
// Accumulate counters.
for (int c = 0; c<COUNTER_LAST; c++) {
if (counter::masterOnly(counter_e(c)) && t != 0)
continue;
@@ -553,9 +534,9 @@ void kmp_stats_output_module::outputStats(const char* heading)
}
fprintf (statsOut, "Aggregate for all threads\n");
printStats (statsOut, &allStats[0], true);
printTimerStats (statsOut, &allStats[0], &totalStats[0]);
fprintf (statsOut, "\n");
printStats (statsOut, &allCounters[0], false);
printCounterStats (statsOut, &allCounters[0]);
if (statsOut != stderr)
fclose(statsOut);
+28 -25
View File
@@ -47,9 +47,8 @@ class stats_flags_e {
public:
const static int onlyInMaster = 1<<0; //!< statistic is valid only for master
const static int noUnits = 1<<1; //!< statistic doesn't need units printed next to it in output
const static int synthesized = 1<<2; //!< statistic's value is created atexit time in the __kmp_output_stats function
const static int notInMaster = 1<<3; //!< statistic is valid for non-master threads
const static int logEvent = 1<<4; //!< statistic can be logged when KMP_STATS_EVENTS is on (valid only for timers)
const static int notInMaster = 1<<2; //!< statistic is valid for non-master threads
const static int logEvent = 1<<3; //!< statistic can be logged when KMP_STATS_EVENTS is on (valid only for timers)
};
/*!
@@ -108,34 +107,38 @@ class stats_flags_e {
*
* @ingroup STATS_GATHERING2
*/
#define KMP_FOREACH_TIMER(macro, arg) \
macro (OMP_start_end, stats_flags_e::onlyInMaster, arg) \
macro (OMP_serial, stats_flags_e::onlyInMaster, arg) \
macro (OMP_work, 0, arg) \
macro (Total_work, stats_flags_e::synthesized, arg) \
macro (OMP_barrier, 0, arg) \
macro (Total_barrier, stats_flags_e::synthesized, arg) \
macro (FOR_static_iterations, stats_flags_e::noUnits, arg) \
macro (FOR_static_scheduling, 0, arg) \
macro (FOR_dynamic_iterations, stats_flags_e::noUnits, arg) \
macro (FOR_dynamic_scheduling, 0, arg) \
macro (TASK_execution, 0, arg) \
macro (OMP_set_numthreads, stats_flags_e::noUnits, arg) \
macro (OMP_PARALLEL_args, stats_flags_e::noUnits, arg) \
macro (OMP_single, 0, arg) \
macro (OMP_master, 0, arg) \
KMP_FOREACH_DEVELOPER_TIMER(macro, arg) \
#define KMP_FOREACH_TIMER(macro, arg) \
macro (OMP_start_end, stats_flags_e::onlyInMaster, arg) \
macro (OMP_serial, stats_flags_e::onlyInMaster, arg) \
macro (OMP_work, 0, arg) \
macro (OMP_barrier, 0, arg) \
macro (FOR_static_scheduling, 0, arg) \
macro (FOR_dynamic_scheduling, 0, arg) \
macro (TASK_execution, 0, arg) \
macro (OMP_single, 0, arg) \
macro (OMP_master, 0, arg) \
macro (OMP_set_numthreads, stats_flags_e::noUnits, arg) \
macro (OMP_PARALLEL_args, stats_flags_e::noUnits, arg) \
macro (FOR_static_iterations, stats_flags_e::noUnits, arg) \
macro (FOR_dynamic_iterations, stats_flags_e::noUnits, arg) \
KMP_FOREACH_DEVELOPER_TIMER(macro, arg) \
macro (LAST,0, arg)
// OMP_start_end -- time from when OpenMP is initialized until the stats are printed at exit
// OMP_serial -- thread zero time executing serial code
// OMP_work -- elapsed time in code dispatched by a fork (measured in the thread)
// Total_work -- a synthesized statistic summarizing how much parallel work each thread executed.
// OMP_barrier -- time at "real" barriers
// Total_barrier -- a synthesized statistic summarizing how much time at real barriers in each thread
// OMP_barrier -- time at "real" barriers (includes task time)
// TASK_execution -- time spent executing tasks
// FOR_static_iterations -- Available parallelism in statically scheduled for loops
// FOR_dynamic_iterations -- Available parallelism in dynamically scheduled for loops
// FOR_static_scheduling -- time spent doing scheduling for a static "for"
// FOR_dynamic_scheduling -- time spent doing scheduling for a dynamic "for"
// OMP_set_numthreads -- Values passed to omp_set_num_threads
// OMP_PARALLEL_args -- Number of arguments passed to a parallel region
// OMP_single
#if (KMP_DEVELOPER_STATS)
// Timers which are of interest tio runtime library developers, not end users.
@@ -276,7 +279,6 @@ class timeStat : public statistic
static bool masterOnly (timer_e e) { return timerInfo[e].flags & stats_flags_e::onlyInMaster; }
static bool workerOnly (timer_e e) { return timerInfo[e].flags & stats_flags_e::notInMaster; }
static bool noUnits (timer_e e) { return timerInfo[e].flags & stats_flags_e::noUnits; }
static bool synthesized(timer_e e) { return timerInfo[e].flags & stats_flags_e::synthesized; }
static bool logEvent (timer_e e) { return timerInfo[e].flags & stats_flags_e::logEvent; }
static void clearEventFlags() {
int i;
@@ -573,7 +575,8 @@ class kmp_stats_output_module {
void init();
static void setupEventColors();
static void printPloticusFile();
static void printStats(FILE *statsOut, statistic const * theStats, bool areTimers);
static void printTimerStats(FILE *statsOut, statistic const * theStats, statistic const * totalStats);
static void printCounterStats(FILE *statsOut, statistic const * theStats);
static void printCounters(FILE * statsOut, counter const * theCounters);
static void printEvents(FILE * eventsOut, kmp_stats_event_vector* theEvents, int gtid);
static rgb_color getEventColor(timer_e e) { return timerColorInfo[e]; }