eztimer
Easy timing of C++ functions
Loading...
Searching...
No Matches
eztimer.hpp
Go to the documentation of this file.
1#ifndef EZTIMER_HPP
2#define EZTIMER_HPP
3
4#include <chrono>
5#include <vector>
6#include <string>
7#include <cstddef>
8#include <random>
9#include <optional>
10#include <functional>
11#include <cassert>
12
22namespace eztimer {
23
27struct Options {
32 int iterations = 10;
33
38 int burn_in = 1;
39
43 unsigned long long seed = 123456;
44
53 std::optional<std::chrono::duration<double> > max_time_per_function;
54
63 std::optional<std::chrono::duration<double> > max_time_total;
64
71 std::function<void()> setup;
72};
73
77struct Timings {
81 std::vector<std::chrono::duration<double> > times;
82
86 std::chrono::duration<double> mean = std::chrono::duration<double>(0);
87
91 std::chrono::duration<double> sd = std::chrono::duration<double>(0);
92};
93
112template<typename Result_>
113std::vector<Timings> time(
114 const std::vector<std::function<Result_()> >& funs,
115 const std::function<void(const Result_&, std::size_t)>& check,
116 const Options& opt
117) {
118 const auto nfun = funs.size();
119 const int num_iterations = opt.iterations + opt.burn_in;
120
121 // Create a random execution sequence, so no function gets a consistent
122 // benefit from running after another function.
123 std::mt19937_64 rng(opt.seed);
124 std::vector<std::size_t> order;
125 order.reserve(num_iterations * nfun);
126 for (int i = 0; i < num_iterations; ++i) {
127 for (std::size_t f = 0; f < nfun; ++f) {
128 order.push_back(f);
129 }
130 std::shuffle(order.end() - nfun, order.end(), rng);
131 }
132
133 std::vector<Timings> output(nfun);
134 auto total_time = std::chrono::duration<double>(0);
135 auto oIt = order.begin();
136
137 for (int i = 0; i < num_iterations; ++i) {
138 if (opt.setup) {
139 opt.setup();
140 }
141
142 for (std::size_t f = 0; f < nfun; ++f, ++oIt) {
143 const auto current = *oIt;
144 auto& curout = output[current];
145
146 if (i >= opt.burn_in) {
147 if (opt.max_time_per_function.has_value() && curout.mean >= *(opt.max_time_per_function)) {
148 continue;
149 }
150 if (opt.max_time_total.has_value() && total_time >= *(opt.max_time_total)) {
151 continue;
152 }
153 }
154
155 const auto start = std::chrono::steady_clock::now();
156 auto res = funs[current]();
157 const auto end = std::chrono::steady_clock::now();
158 const auto curtime = std::chrono::duration_cast<std::chrono::duration<double> >(end - start);
159 curout.times.push_back(curtime);
160
161 if (i >= opt.burn_in) {
162 check(res, current);
163 curout.mean += curtime;
164 if (opt.max_time_total.has_value()) {
165 total_time += curtime;
166 }
167 }
168 }
169 }
170
171 assert(oIt == order.end());
172 for (auto& curout : output) {
173 // Throwing away the burn-in cycles. We add them and throw them away to
174 // ensure that the compiler doesn't just optimize out the calls.
175 curout.times.erase(curout.times.begin(), curout.times.begin() + opt.burn_in);
176 if (curout.times.empty()) {
177 continue;
178 }
179
180 // Computing the remaining statistics.
181 curout.mean /= curout.times.size();
182 for (const auto id : curout.times) {
183 const double delta = (id - curout.mean).count();
184 curout.sd += std::chrono::duration<double>(delta * delta);
185 }
186 curout.sd /= curout.times.size() - 1;
187 curout.sd = std::chrono::duration<double>(std::sqrt(curout.sd.count()));
188 }
189
190 return output;
191}
192
193}
194
195#endif
Easy timing of C++ functions.
std::vector< Timings > time(const std::vector< std::function< Result_()> > &funs, const std::function< void(const Result_ &, std::size_t)> &check, const Options &opt)
Definition eztimer.hpp:113
Options for time().
Definition eztimer.hpp:27
int burn_in
Definition eztimer.hpp:38
unsigned long long seed
Definition eztimer.hpp:43
int iterations
Definition eztimer.hpp:32
std::optional< std::chrono::duration< double > > max_time_per_function
Definition eztimer.hpp:53
std::function< void()> setup
Definition eztimer.hpp:71
std::optional< std::chrono::duration< double > > max_time_total
Definition eztimer.hpp:63
Timings for each function.
Definition eztimer.hpp:77
std::vector< std::chrono::duration< double > > times
Definition eztimer.hpp:81
std::chrono::duration< double > sd
Definition eztimer.hpp:91
std::chrono::duration< double > mean
Definition eztimer.hpp:86