6#ifndef CHEBYSHEV_BENCHMARK_H
7#define CHEBYSHEV_BENCHMARK_H
43 template<
typename InputType,
typename Function>
45 Function func,
const std::vector<InputType>& input) {
47 if (input.size() == 0)
51 __volatile__
auto c = func(input[0]);
55 for (
unsigned int j = 0; j < input.size(); ++j)
88 "name",
"averageRuntime",
"stdevRuntime",
"runsPerSecond"
108 std::map <std::string, std::vector<benchmark_result>> benchmarkResults {};
111 std::mutex benchmarkMutex;
114 std::vector<std::thread> benchmarkThreads {};
118 bool wasTerminated {
false};
127 std::shared_ptr<output::output_context>
output;
131 std::shared_ptr<random::random_context>
random;
141 std::string moduleName,
143 const char** argv =
nullptr) {
147 output = std::make_shared<output::output_context>();
148 random = std::make_shared<random::random_context>();
152 for (
int i = 1; i < argc; ++i)
155 output->info(
"Starting benchmarks of the " + moduleName +
" module ...");
158 benchmarkResults.clear();
159 wasTerminated =
false;
172 std::lock_guard<std::mutex> lock(benchmarkMutex);
174 unsigned int totalBenchmarks = 0;
175 unsigned int failedBenchmarks = 0;
177 for (
const auto& pair : benchmarkResults) {
178 for (
const auto& testCase : pair.second) {
180 failedBenchmarks += testCase.failed ? 1 : 0;
186 if(
output->settings.outputToFile &&
187 !
output->settings.outputFiles.size() &&
196 std::vector<std::string> outputFiles;
212 double percent = totalBenchmarks > 0 ? (failedBenchmarks / (double) totalBenchmarks) * 100 : 0;
215 std::to_string(totalBenchmarks) +
" total benchmarks, " +
216 std::to_string(failedBenchmarks) +
" failed (" + std::to_string(percent).substr(0, 4) +
"%)"
219 if (totalBenchmarks == 0)
220 output->warn(
"No benchmarks were executed!");
224 std::exit(failedBenchmarks);
227 wasTerminated =
true;
233 std::string moduleName,
int argc = 0,
234 const char** argv =
nullptr) {
236 setup(moduleName, argc, argv);
251 std::lock_guard<std::mutex> lock(benchmarkMutex);
252 benchmarkResults = other.benchmarkResults;
262 std::lock_guard<std::mutex> lock(benchmarkMutex);
263 benchmarkResults = other.benchmarkResults;
282 template<
typename InputType =
double,
typename Function>
284 const std::string& name,
286 const std::vector<InputType>& input,
287 unsigned int runs = 0,
288 bool quiet =
false) {
293 output->debug(
"Running benchmark: " + name);
295 auto task = [
this, name, func, input, runs, quiet]() {
313 totalRuntime =
runtime(func, input);
314 averageRuntime = totalRuntime / input.size();
317 for (
unsigned int i = 1; i < runs; ++i) {
322 const prec_t currentAverage = currentRun / input.size();
323 totalRuntime += currentRun;
325 const prec_t tmp = averageRuntime;
326 averageRuntime = tmp + (currentAverage - tmp) / (i + 1);
327 sumSquares += (currentAverage - tmp)
328 * (currentAverage - averageRuntime);
340 res.iterations = input.size();
341 res.totalRuntime = totalRuntime;
342 res.averageRuntime = averageRuntime;
343 res.runsPerSecond = 1000.0 / res.averageRuntime;
348 res.stdevRuntime = std::sqrt(sumSquares / (runs - 1));
350 std::lock_guard<std::mutex> lock(benchmarkMutex);
351 benchmarkResults[name].push_back(res);
355 benchmarkThreads.emplace_back(task) : task();
365 template <
typename InputType =
double,
typename Function>
367 const std::string& name,
374 output->debug(
"Running benchmark: " + name);
382 std::vector<InputType> input (opt.
iterations);
384 for (
unsigned int i = 0; i < opt.
iterations; ++i)
390 auto task = [
this, input, name, func, opt, seed]() {
408 totalRuntime =
runtime(func, input);
409 averageRuntime = totalRuntime / input.size();
412 for (
unsigned int i = 1; i < opt.
runs; ++i) {
417 const prec_t currentAverage = currentRun / input.size();
418 totalRuntime += currentRun;
420 const prec_t tmp = averageRuntime;
421 averageRuntime = tmp + (currentAverage - tmp) / (i + 1);
422 sumSquares += (currentAverage - tmp)
423 * (currentAverage - averageRuntime);
435 res.iterations = input.size();
436 res.totalRuntime = totalRuntime;
437 res.averageRuntime = averageRuntime;
438 res.runsPerSecond = 1000.0 / res.averageRuntime;
440 res.quiet = opt.
quiet;
444 res.stdevRuntime = std::sqrt(sumSquares / (opt.
runs - 1));
446 std::lock_guard<std::mutex> lock(benchmarkMutex);
447 benchmarkResults[name].push_back(res);
451 benchmarkThreads.emplace_back(task) : task();
463 template<
typename InputType =
double,
typename Function>
465 const std::string& name,
468 unsigned int runs = 0,
469 unsigned int iterations = 0,
470 bool quiet =
false) {
491 for (
auto& t : benchmarkThreads)
495 benchmarkThreads.clear();
505 inline std::vector<benchmark_result>
get_benchmark(
const std::string& name) {
508 return benchmarkResults[name];
521 return benchmarkResults[name].at(i);
533 int argc = 0,
const char** argv =
nullptr) {
Structures for the benchmark module.
Benchmark module context, handling benchmark requests concurrently.
Definition benchmark.h:103
void wait_results()
Wait for all concurrent benchmarks to finish execution.
Definition benchmark.h:489
benchmark_context(std::string moduleName, int argc=0, const char **argv=nullptr)
Default constructor setting up the context.
Definition benchmark.h:232
benchmark_context(const benchmark_context &other)
Custom copy constructor to avoid copying std::mutex.
Definition benchmark.h:249
void benchmark(const std::string &name, Function func, benchmark_options< InputType > opt)
Run a benchmark on a generic function, with the given options.
Definition benchmark.h:366
benchmark_context & operator=(const benchmark_context &other)
Custom assignment operator to avoid copying std::mutex.
Definition benchmark.h:260
void setup(std::string moduleName, int argc=0, const char **argv=nullptr)
Setup the benchmark environment.
Definition benchmark.h:140
void benchmark(const std::string &name, Function func, InputGenerator< InputType > inputGenerator, unsigned int runs=0, unsigned int iterations=0, bool quiet=false)
Run a benchmark on a generic function, with the given argument options.
Definition benchmark.h:464
std::shared_ptr< random::random_context > random
Random module settings for the context, dynamically allocated and possibly shared between multiple co...
Definition benchmark.h:131
std::vector< benchmark_result > get_benchmark(const std::string &name)
Get a list of benchmarks results associated to the given name or label.
Definition benchmark.h:505
benchmark_result get_benchmark(const std::string &name, unsigned int i)
Get a benchmark result associated to the given name or label and index.
Definition benchmark.h:518
void benchmark(const std::string &name, Function func, const std::vector< InputType > &input, unsigned int runs=0, bool quiet=false)
Run a benchmark on a generic function, with the given input vector.
Definition benchmark.h:283
benchmark_settings settings
Settings for the benchmark context.
Definition benchmark.h:123
~benchmark_context()
Terminate the benchmark module.
Definition benchmark.h:241
std::shared_ptr< output::output_context > output
Output module settings for the context, dynamically allocated and possibly shared between multiple co...
Definition benchmark.h:127
void terminate(bool exit=false)
Terminate the benchmarking environment.
Definition benchmark.h:167
Timer class to measure elapsed time in milliseconds.
Definition timer.h:18
long double prec_t
Floating-point type of higher precision, used in computations, such as error estimation.
Definition common.h:42
#define CHEBYSHEV_BENCHMARK_ITER
Default number of benchmark iterations.
Definition common.h:22
#define CHEBYSHEV_BENCHMARK_RUNS
Default number of benchmark runs.
Definition common.h:27
Input generators for benchmarks.
long double runtime(Function func, const std::vector< InputType > &input)
Measure the total runtime of a function over the given input for a single run.
Definition benchmark.h:44
std::function< InputType(random::random_source &)> InputGenerator
A function which takes in a random source and returns a generated input element.
Definition benchmark_structures.h:65
benchmark_context make_context(const std::string &moduleName, int argc=0, const char **argv=nullptr)
Construct a benchmarking context with the given parameters.
Definition benchmark.h:532
General namespace of the framework.
Definition benchmark.h:22
The output module, with formatting capabilities.
The pseudorandom number generation and sampling module.
A structure holding the options of a benchmark.
Definition benchmark_structures.h:71
unsigned int iterations
Number of iterations.
Definition benchmark_structures.h:77
uint64_t seed
The seed to use for randomized input generation (by default, a random seed is generated using the ran...
Definition benchmark_structures.h:87
bool quiet
Whether to print to standard output or not.
Definition benchmark_structures.h:83
unsigned int runs
Number of runs (run with the same input values).
Definition benchmark_structures.h:74
InputGenerator< InputType > inputGenerator
The function to use to generate input for the benchmark.
Definition benchmark_structures.h:80
Structure holding the results of a benchmark.
Definition benchmark_structures.h:23
std::string name
Identifying name of the function or test case.
Definition benchmark_structures.h:26
Global settings of the benchmark module, used in benchmark_context.
Definition benchmark.h:64
std::vector< std::string > benchmarkOutputFiles
The files to write benchmark results to (if empty, all results are output to a generic file).
Definition benchmark.h:84
unsigned int defaultRuns
Default number of runs.
Definition benchmark.h:73
std::map< std::string, bool > pickedBenchmarks
Target benchmarks marked for execution (all benchmarks will be executed if empty)
Definition benchmark.h:80
std::vector< std::string > benchmarkColumns
Default columns to print for benchmarks.
Definition benchmark.h:87
std::string moduleName
Name of the module currently being benchmarked.
Definition benchmark.h:67
bool multithreading
Whether to use multithreading for the execution of benchmarks (defaults to true).
Definition benchmark.h:96
unsigned int defaultIterations
Default number of iterations.
Definition benchmark.h:70
std::vector< std::string > outputFiles
The files to write all benchmark results to.
Definition benchmark.h:76
A source of pseudorandom numbers.
Definition random.h:39
uint64_t get_seed()
Get the seed used to generate the random source.
Definition random.h:59
A timer class to measure elapsed time in milliseconds.