Teuchos - Trilinos Tools Package  Version of the Day
Teuchos_StackedTimer.cpp
1 // @HEADER BEGIN
2 // @HEADER END
3 
4 #include "Teuchos_StackedTimer.hpp"
5 #include <limits>
6 
7 
8 namespace Teuchos {
9 
10 
12  level_(std::numeric_limits<unsigned>::max()),name_("INVALID"),parent_(NULL)
13 {}
14 
15 void error_out(const std::string& msg, const bool)
16 {
17  TEUCHOS_TEST_FOR_EXCEPTION(true,std::runtime_error,msg);
18 }
19 
20 
21 void
23  for (unsigned i=0; i<level_; ++i)
24  os << " ";
25  os << name_<<":"<<accumulatedTime()<< " [" << count_started_<<"] ("<< count_updates_ <<")"<<std::endl;
26  double t_total = 0;
27  for (size_t i=0; i<sub_timers_.size(); ++i) {
28  t_total += sub_timers_[i].accumulatedTime();
29  sub_timers_[i].report(os);
30  }
31  if ( sub_timers_.size() == 0 )
32  return;
33  for (unsigned i=0; i<=level_; ++i)
34  os << " ";
35  os << "Remainder: " << accumulatedTime() - t_total<<std::endl;
36 
37 }
38 
39 BaseTimer::TimeInfo
40 StackedTimer::LevelTimer::findTimer(const std::string &name, bool& found) {
41  BaseTimer::TimeInfo t;
42  if (get_full_name() == name) {
43  t = BaseTimer::TimeInfo(this);
44  found = true;
45  }
46  else {
47  for (unsigned i=0;i<sub_timers_.size(); ++i){
48  t = sub_timers_[i].findTimer(name,found);
49  if (found)
50  return t;
51  }
52  }
53  return t;
54 }
55 
56 void
58  int num_timers = timer_.countTimers();
59  flat_names_.resize(num_timers);
60  unsigned pos=0;
61  timer_.addTimerNames(flat_names_, pos);
62 }
63 
64 void
66  Array<std::string> all_names;
67  mergeCounterNames(*comm, flat_names_, all_names, Union);
68  flat_names_ = all_names;
69 }
70 
71 void
73  // allocate everything
74  int num_names = flat_names_.size();
75  sum_.resize(num_names);
76  count_.resize(num_names);
77  active_.resize(num_names);
78 
79  if (options.output_minmax || options.output_histogram) {
80  min_.resize(num_names);
81  max_.resize(num_names);
82  if ( options.output_minmax )
83  sum_sq_.resize(num_names);
84  }
85 
86 
87  if (options.output_histogram ) {
88  hist_.resize(options.num_histogram);
89  for (int i=0;i<options.num_histogram ; ++i)
90  hist_[i].resize(num_names);
91  }
92 
93  // Temp data
94  Array<double> time(num_names);
95  Array<unsigned long> count(num_names);
97  if (options.output_total_updates)
98  updates.resize(num_names);
99  Array<int> used(num_names);
100  Array<int> bins;
101 
102  if (options.output_histogram)
103  bins.resize(num_names);
104 
105  // set initial values
106  for (int i=0;i<num_names; ++i) {
107  bool found = false; // ignore result here
108  auto t = timer_.findTimer(flat_names_[i],found);
109  time[i] = t.time;
110  count[i] = t.count;
111  used[i] = t.count==0? 0:1;
112  if (options.output_total_updates)
113  updates[i] = t.updates;
114  }
115 
116  // Now reduce the data
117  reduce<int, double>(time.getRawPtr(), sum_.getRawPtr(), num_names, REDUCE_SUM, 0, *comm);
118  reduce(count.getRawPtr(), count_.getRawPtr(), num_names, REDUCE_SUM, 0, *comm);
119  reduce(used.getRawPtr(), active_.getRawPtr(), num_names, REDUCE_SUM, 0, *comm);
120 
121  if (min_.size()) {
122  reduceAll(*comm, REDUCE_MIN, num_names, time.getRawPtr(), min_.getRawPtr());
123  reduceAll(*comm, REDUCE_MAX, num_names, time.getRawPtr(), max_.getRawPtr());
124  }
125 
126  if (options.output_histogram) {
127  for (int i=0;i<num_names; ++i) {
128 
129  double dh = (max_[i]-min_[i])/options.num_histogram;
130  if (dh==0) // Put everything into bin 1
131  dh=1;
132  if (used[i]) {
133  int bin=(time[i]- min_[i])/dh;
134  bins[i] = std::max(std::min(bin,options.num_histogram-1) , 0);
135  }
136  }
137  // Recycle the used array for the temp bin array
138  for (int j=0; j<options.num_histogram; ++j){
139  for (int i=0;i<num_names; ++i) {
140  if (bins[i] == j )
141  used[i]=1;
142  else
143  used[i]=0;
144  }
145  reduce(used.getRawPtr(), hist_[j].getRawPtr(), num_names, REDUCE_SUM, 0, *comm);
146  }
147  }
148 
149  if (sum_sq_.size()) {
150  for (int i=0;i<num_names; ++i)
151  time[i] *= time[i];
152  reduce(time.getRawPtr(), sum_sq_.getRawPtr(), num_names, REDUCE_SUM, 0, *comm);
153  }
154 
155 }
156 
157 std::pair<std::string, std::string> getPrefix(const std::string &name) {
158  for (std::size_t i=name.size()-1; i>0; --i)
159  if (name[i] == '@') {
160  return std::pair<std::string, std::string>(name.substr(0,i), name.substr(i+1, name.size()));
161  }
162  return std::pair<std::string, std::string>(std::string(""), name);
163 }
164 
165 
166 double
167 StackedTimer::printLevel (std::string prefix, int print_level, std::ostream &os, std::vector<bool> &printed, double parent_time, const OutputOptions &options) {
168  double total_time = 0.0;
169 
170  for (int i=0; i<flat_names_.size(); ++i ) {
171  if (printed[i])
172  continue;
173  int level = std::count(flat_names_[i].begin(), flat_names_[i].end(), '@');
174  if ( (level != print_level) || (level >= options.max_levels) )
175  continue;
176  auto split_names = getPrefix(flat_names_[i]);
177  if ( prefix != split_names.first)
178  continue;
179 
180  // Output the data
181  for (int l=0; l<level; ++l)
182  os << "| ";
183  os << split_names.second << ": ";
184  // output averge time
185  os << sum_[i]/active_[i];
186  // output percentage
187  if ( options.output_fraction && parent_time>0)
188  os << " - "<<sum_[i]/active_[i]/parent_time*100<<"%";
189  // output count
190  os << " ["<<count_[i]/active_[i]<<"]";
191  // output total counts
192  if ( options.output_total_updates )
193  os << " ("<<updates_[i]/active_[i]<<")";
194  // Output min and maxs
195  if ( options.output_minmax && active_[i]>1) {
196  os << " {min="<<min_[i]<<", max="<<max_[i];
197  if (active_[i]>1)
198  os<<", std dev="<<sqrt((sum_sq_[i]-sum_[i]*sum_[i]/active_[i])/(active_[i]-1));
199  os << "}";
200  }
201  // Output histogram
202  if ( options.output_histogram && active_[i] >1 ) {
203  // dump the histogram
204  os << " <";
205  for (int h=0;h<options.num_histogram; ++h) {
206  if (h)
207  os <<", "<<hist_[h][i];
208  else
209  os << hist_[h][i];
210  }
211  os << ">";
212  }
213  os << std::endl;
214  printed[i] = true;
215  double sub_time = printLevel(flat_names_[i], level+1, os, printed, sum_[i]/active_[i], options);
216  if (sub_time > 0 ) {
217  for (int l=0; l<=level; ++l)
218  os << "| ";
219  os << "Remainder: " << sum_[i]/active_[i]- sub_time;
220  if ( options.output_fraction && (sum_[i]/active_[i] > 0.) )
221  os << " - "<< (sum_[i]/active_[i]- sub_time)/(sum_[i]/active_[i])*100 << "%";
222  os <<std::endl;
223  }
224  total_time += sum_[i]/active_[i];
225  }
226  return total_time;
227 }
228 
229 void
230 StackedTimer::report(std::ostream &os, Teuchos::RCP<const Teuchos::Comm<int> > comm, OutputOptions options) {
231  flatten();
232  merge(comm);
233  collectRemoteData(comm, options);
234  if (rank(*comm) == 0 ) {
235  if (options.print_warnings) {
236  os << "*** Teuchos::StackedTimer::report() - Remainder for a block will be ***"
237  << "\n*** incorrect if a timer in the block does not exist on every rank ***"
238  << "\n*** of the MPI Communicator. ***"
239  << std::endl;
240  }
241  if ( (options.max_levels != INT_MAX) && options.print_warnings) {
242  os << "Teuchos::StackedTimer::report() - max_levels set to " << options.max_levels
243  << ", to print more levels, increase value of OutputOptions::max_levels." << std::endl;
244  }
245  std::vector<bool> printed(flat_names_.size(), false);
246  printLevel("", 0, os, printed, 0., options);
247  }
248 }
249 
250 } //namespace Teuchos
Teuchos::Array::size
size_type size() const
Definition: Teuchos_Array.hpp:1017
Teuchos::Array::resize
void resize(size_type new_size, const value_type &x=value_type())
Definition: Teuchos_Array.hpp:1033
Teuchos::StackedTimer::printLevel
double printLevel(std::string prefix, int level, std::ostream &os, std::vector< bool > &printed, double parent_time, const OutputOptions &options)
Definition: Teuchos_StackedTimer.cpp:167
Teuchos::REDUCE_MAX
Max.
Definition: Teuchos_EReductionType.hpp:74
Teuchos::StackedTimer::LevelTimer::LevelTimer
LevelTimer()
Default constructor, shouldn't be used but needed for std::vector.
Definition: Teuchos_StackedTimer.cpp:11
Teuchos::StackedTimer::LevelTimer::countTimers
int countTimers()
Definition: Teuchos_StackedTimer.hpp:273
Teuchos::StackedTimer::merge
void merge(Teuchos::RCP< const Teuchos::Comm< int > > comm)
Definition: Teuchos_StackedTimer.cpp:65
Teuchos::RCP
Smart reference counting pointer class for automatic garbage collection.
Definition: Teuchos_RCPDecl.hpp:429
Teuchos::Array< std::string >
Teuchos::REDUCE_SUM
Sum.
Definition: Teuchos_EReductionType.hpp:72
Teuchos::StackedTimer::timer_
LevelTimer timer_
Base timer.
Definition: Teuchos_StackedTimer.hpp:532
Teuchos::error_out
void error_out(const std::string &msg, const bool)
Error reporting function for stacked timer.
Definition: Teuchos_StackedTimer.cpp:15
Teuchos::StackedTimer::accumulatedTime
double accumulatedTime(const std::string &name="")
Definition: Teuchos_StackedTimer.hpp:459
Teuchos::StackedTimer::collectRemoteData
void collectRemoteData(Teuchos::RCP< const Teuchos::Comm< int > > comm, const OutputOptions &options)
Definition: Teuchos_StackedTimer.cpp:72
Teuchos::reduceAll
TEUCHOS_DEPRECATED void reduceAll(const Comm< Ordinal > &comm, const EReductionType reductType, const Packet &send, Packet *globalReduct)
Deprecated .
Definition: Teuchos_CommHelpers.hpp:377
Teuchos::StackedTimer::OutputOptions
Struct for controlling output options like histograms.
Definition: Teuchos_StackedTimer.hpp:507
Teuchos::Array::getRawPtr
T * getRawPtr()
Return a raw pointer to beginning of array or NULL if unsized.
Definition: Teuchos_Array.hpp:1365
Teuchos::mergeCounterNames
void mergeCounterNames(const Comm< int > &comm, const Array< std::string > &localNames, Array< std::string > &globalNames, const ECounterSetOp setOp)
Merge counter names over all processors.
Definition: Teuchos_PerformanceMonitorBase.cpp:515
Teuchos::REDUCE_MIN
Min.
Definition: Teuchos_EReductionType.hpp:73
Teuchos::StackedTimer::flatten
void flatten()
Definition: Teuchos_StackedTimer.cpp:57
Teuchos::StackedTimer::LevelTimer::report
void report(std::ostream &os)
Definition: Teuchos_StackedTimer.cpp:22
Teuchos::Comm
Abstract interface for distributed-memory communication.
Definition: Teuchos_Comm.hpp:85
Teuchos::StackedTimer::LevelTimer::findTimer
BaseTimer::TimeInfo findTimer(const std::string &name, bool &found)
Definition: Teuchos_StackedTimer.cpp:40
Teuchos
The Teuchos namespace contains all of the classes, structs and enums used by Teuchos,...
TEUCHOS_TEST_FOR_EXCEPTION
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.
Definition: Teuchos_TestForException.hpp:170