dune-pdelab  2.5-dev
benchmarkhelper.hh
Go to the documentation of this file.
1 #ifndef DUNE_PDELAB_COMMON_BENCHMARKHELPER_HH
2 #define DUNE_PDELAB_COMMON_BENCHMARKHELPER_HH
3 
4 #include <ostream>
5 #include <iomanip>
6 #include <map>
7 #include <string>
8 #include <vector>
9 #include <limits>
10 #include <cmath>
11 
12 #include <dune/common/exceptions.hh>
13 #include <dune/common/ios_state.hh>
14 
15 #include <ctime>
16 
17 namespace Dune {
18  namespace PDELab {
19 
21  {
22 
23  double operator()() const
24  {
25  return static_cast<double>(std::clock()) / static_cast<double>(CLOCKS_PER_SEC);
26  }
27 
28  };
29 
30 #if HAVE_MPI
31 #include"mpi.h"
32 
34  {
35 
36  double operator()() const
37  {
38  return MPI_Wtime();
39  }
40 
41  };
42 
44 
45 #else
46 
48 
49 #endif
50 
51  struct Timing
52  {
53  double start;
54  double end;
55 
56  double elapsed() const
57  {
58  return end - start;
59  }
60 
61  };
62 
64  {
65  std::vector<Timing> timings;
66  double min;
67  double max;
68  double avg;
69  double std_dev;
70  };
71 
72  template<typename TimeSource = DefaultTimeSource>
74  {
75 
76  BenchmarkHelper(std::string name, std::size_t max_runs = 1, TimeSource timeSource = TimeSource())
77  : _name(name)
78  , _time(timeSource)
79  , _run(0)
80  , _max_runs(max_runs)
81  , _statistics_stale(true)
82  {
83  _run_times.timings.resize(max_runs);
84  }
85 
86 
87  void start_run()
88  {
89  if (_run >= _max_runs)
90  {
91  DUNE_THROW(Dune::RangeError,"maximum number of benchmark runs exceeded");
92  }
93  _statistics_stale = true;
94  _run_times.timings[_run].start = _time();
95  }
96 
97  void start_run(std::ostream& s)
98  {
99  start_run();
100  ios_base_all_saver ios_saver(s);
101  s << _name << " (" << std::setw(2) << _run << " of " << std::setw(2) << _max_runs << ") " << std::flush;
102  }
103 
104 
105  void end_run()
106  {
107  _run_times.timings[_run].end = _time();
108  ++_run;
109  }
110 
111  void end_run(std::ostream& s)
112  {
113  end_run();
114  ios_base_all_saver ios_saver(s);
115  s << " " << std::setw(10) << std::setprecision(3) << _run_times.timings[_run-1].elapsed() << " sec" << std::endl;
116  }
117 
118  void start(std::string task)
119  {
120  std::pair<
121  std::map<std::string,BenchmarkEntry>::iterator,
122  bool
123  > res = _tasks.insert(make_pair(task,BenchmarkEntry()));
124  if (res.second)
125  res.first->second.timings.resize(_max_runs);
126  res.first->second.timings[_run].start = _time();
127  _statistics_stale = true;
128  }
129 
130  void start(std::string task, std::ostream& s)
131  {
132  start(task);
133  }
134 
135  void end(std::string task)
136  {
137  _tasks[task].timings[_run].end = _time();
138  _statistics_stale = true;
139  }
140 
141  void end(std::string task, std::ostream& s)
142  {
143  end(task);
144  s << "." << std::flush;
145  }
146 
148  {
149  entry.min = std::numeric_limits<double>::max();
150  entry.max = 0;
151  entry.avg = 0;
152  entry.std_dev = 0;
153 
154  for (std::vector<Timing>::iterator it = entry.timings.begin(), end = entry.timings.end();
155  it != end;
156  ++it)
157  {
158  const double elapsed = it->elapsed();
159  entry.min = std::min(entry.min,elapsed);
160  entry.max = std::max(entry.max,elapsed);
161  entry.avg += elapsed;
162  entry.std_dev += elapsed*elapsed;
163  }
164 
165  entry.avg /= entry.timings.size();
166  entry.std_dev /= entry.timings.size();
167  entry.std_dev = std::sqrt(entry.std_dev - entry.avg*entry.avg);
168  }
169 
171  {
172  _max_name_len = 5; // strlen("total")
173  for (std::map<std::string,BenchmarkEntry>::iterator it = _tasks.begin(), end = _tasks.end();
174  it != end;
175  ++it)
176  {
177  _max_name_len = std::max(_max_name_len,it->first.size());
178  update_entry(it->second);
179  }
180 
181  update_entry(_run_times);
182 
183  _statistics_stale = false;
184  }
185 
186  void print_entry(std::ostream& s, std::string name, const BenchmarkEntry& entry, bool summary_only = false) const
187  {
188  s << std::setw(_max_name_len + 1) << std::left << name
189  << std::right << std::scientific << std::setw(10) << std::setprecision(2);
190  if (!summary_only)
191  for (std::vector<Timing>::const_iterator it = entry.timings.begin(),
192  end = entry.timings.end();
193  it != end;
194  ++it)
195  {
196  s << std::setw(10) << it->elapsed();
197  }
198  s << std::setw(10) << entry.min
199  << std::setw(10) << entry.max
200  << std::setw(10) << entry.avg
201  << std::setw(10) << entry.std_dev;
202 
203  s << std::endl;
204  }
205 
206  void print(std::ostream& s, bool summary_only = false)
207  {
208  ios_base_all_saver ios_saver(s);
209 
210  if (_statistics_stale)
211  update_statistics();
212 
213  s << _name << " (" << std::setw(2) << _run << " of " << std::setw(2) << _max_runs << ") runs" << std::endl;
214 
215  s << std::setw(_max_name_len + 1) << "";
216 
217  if (!summary_only)
218  for (std::size_t i = 0; i < _max_runs; ++i)
219  s << std::setw(10) << i;
220 
221  s << std::setw(10) << "min"
222  << std::setw(10) << "max"
223  << std::setw(10) << "avg"
224  << std::setw(10) << "std_dev" << std::endl;
225 
226  for (std::map<std::string,BenchmarkEntry>::const_iterator it = _tasks.begin(), end = _tasks.end();
227  it != end;
228  ++it)
229  print_entry(s,it->first,it->second,summary_only);
230 
231  print_entry(s,"total",_run_times,summary_only);
232  }
233 
234  private:
235  const std::string _name;
236  TimeSource _time;
237  std::size_t _run;
238  const std::size_t _max_runs;
239  std::map<std::string,BenchmarkEntry> _tasks;
240  bool _statistics_stale;
241  BenchmarkEntry _run_times;
242  std::size_t _max_name_len;
243 
244  };
245 
246 
247 
248  } // namespace PDELAB
249 } // namespace Dune
250 
251 #endif // DUNE_PDELAB_COMMON_BENCHMARKHELPER_HH
Definition: benchmarkhelper.hh:73
double max
Definition: benchmarkhelper.hh:67
double min
Definition: benchmarkhelper.hh:66
void start(std::string task, std::ostream &s)
Definition: benchmarkhelper.hh:130
BenchmarkHelper(std::string name, std::size_t max_runs=1, TimeSource timeSource=TimeSource())
Definition: benchmarkhelper.hh:76
Definition: benchmarkhelper.hh:33
MPIWallTimeSource DefaultTimeSource
Definition: benchmarkhelper.hh:43
void print_entry(std::ostream &s, std::string name, const BenchmarkEntry &entry, bool summary_only=false) const
Definition: benchmarkhelper.hh:186
double start
Definition: benchmarkhelper.hh:53
double operator()() const
Definition: benchmarkhelper.hh:36
Definition: benchmarkhelper.hh:63
Definition: benchmarkhelper.hh:20
double std_dev
Definition: benchmarkhelper.hh:69
void update_statistics()
Definition: benchmarkhelper.hh:170
For backward compatibility – Do not use this!
Definition: adaptivity.hh:28
void start_run()
Definition: benchmarkhelper.hh:87
double end
Definition: benchmarkhelper.hh:54
void start_run(std::ostream &s)
Definition: benchmarkhelper.hh:97
void end_run()
Definition: benchmarkhelper.hh:105
void update_entry(BenchmarkEntry &entry)
Definition: benchmarkhelper.hh:147
void end_run(std::ostream &s)
Definition: benchmarkhelper.hh:111
void start(std::string task)
Definition: benchmarkhelper.hh:118
void end(std::string task, std::ostream &s)
Definition: benchmarkhelper.hh:141
double operator()() const
Definition: benchmarkhelper.hh:23
double elapsed() const
Definition: benchmarkhelper.hh:56
double avg
Definition: benchmarkhelper.hh:68
Definition: benchmarkhelper.hh:51
std::vector< Timing > timings
Definition: benchmarkhelper.hh:65
const std::string s
Definition: function.hh:830
void end(std::string task)
Definition: benchmarkhelper.hh:135
void print(std::ostream &s, bool summary_only=false)
Definition: benchmarkhelper.hh:206