diff options
author | David Robillard <d@drobilla.net> | 2018-08-26 23:16:00 +0200 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2018-09-29 14:50:34 +0200 |
commit | 0a5a45ff8ae437ddf1c3b8de425f30a44e6f5580 (patch) | |
tree | 870b40f80575969ab5bb7771d62ecb0bdf13662a /test/bench_bitvec.cpp | |
parent | a115beb0d3fedbe3d286ad1ba2dd7af319f7968d (diff) | |
download | chilbert-0a5a45ff8ae437ddf1c3b8de425f30a44e6f5580.tar.gz chilbert-0a5a45ff8ae437ddf1c3b8de425f30a44e6f5580.tar.bz2 chilbert-0a5a45ff8ae437ddf1c3b8de425f30a44e6f5580.zip |
Add benchmarks
Diffstat (limited to 'test/bench_bitvec.cpp')
-rw-r--r-- | test/bench_bitvec.cpp | 339 |
1 files changed, 339 insertions, 0 deletions
diff --git a/test/bench_bitvec.cpp b/test/bench_bitvec.cpp new file mode 100644 index 0000000..741b2d2 --- /dev/null +++ b/test/bench_bitvec.cpp @@ -0,0 +1,339 @@ +/* + Copyright (C) 2018 David Robillard <d@drobilla.net> + + This program is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free Software + Foundation, either version 2 of the License, or (at your option) any later + version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + details. + + You should have received a copy of the GNU General Public License along with + this program. If not, see <https://www.gnu.org/licenses/>. +*/ + +#include "bench_utils.hpp" + +#include "chilbert/BoundedBitVec.hpp" +#include "chilbert/DynamicBitVec.hpp" +#include "chilbert/SmallBitVec.hpp" +#include "chilbert/StaticBitVec.hpp" + +#include <fstream> + +template <class T, size_t N> +struct BenchAnd +{ + Duration operator()(Context& ctx) + { + const T v = make_random_bitvec<T, N>(ctx); + T r = make_random_bitvec<T, N>(ctx); + + return run_bench([&](auto) { r &= v; }); + } +}; + +template <class T, size_t N> +struct BenchOr +{ + Duration operator()(Context& ctx) + { + const T v = make_random_bitvec<T, N>(ctx); + T r = make_random_bitvec<T, N>(ctx); + + return run_bench([&](auto) { r |= v; }); + } +}; + +template <class T, size_t N> +struct BenchXor +{ + Duration operator()(Context& ctx) + { + const T v = make_random_bitvec<T, N>(ctx); + T r = make_random_bitvec<T, N>(ctx); + + return run_bench([&](auto) { r ^= v; }); + } +}; + +template <class T, size_t N> +struct BenchSetOne +{ + Duration operator()(Context& ctx) + { + T v = make_random_bitvec<T, N>(ctx); + return run_bench([&](const auto i) { v.set(i % N); }); + } +}; + +template <class T, size_t N> +struct BenchSetAll +{ + Duration operator()(Context& ctx) + { + T v = make_random_bitvec<T, N>(ctx); + return run_bench([&](auto) { v.set(); }); + } +}; + +template <class T, size_t N> +struct BenchResetOne +{ + Duration operator()(Context& ctx) + { + T v = make_random_bitvec<T, N>(ctx); + return run_bench([&](const auto i) { v.reset(i % N); }); + } +}; + +template <class T, size_t N> +struct BenchResetAll +{ + Duration operator()(Context& ctx) + { + T v = make_random_bitvec<T, N>(ctx); + return run_bench([&](auto) { v.reset(); }); + } +}; + +template <class T, size_t N> +struct BenchFlipOne +{ + Duration operator()(Context& ctx) + { + T v = make_random_bitvec<T, N>(ctx); + return run_bench([&](const auto i) { v.flip(i % N); }); + } +}; + +template <class T, size_t N> +struct BenchFlipAll +{ + Duration operator()(Context& ctx) + { + T v = make_random_bitvec<T, N>(ctx); + return run_bench([&](auto) { v.flip(); }); + } +}; + +template <class T, size_t N> +struct BenchNone +{ + Duration operator()(Context& ctx) + { + T v = make_random_bitvec<T, N>(ctx); + bool r = false; + return run_bench([&](auto) { r = v.none(); }); + } +}; + +template <class T, size_t N> +struct BenchCount +{ + Duration operator()(Context& ctx) + { + T v = make_random_bitvec<T, N>(ctx); + volatile size_t r = 0; + return run_bench([&](auto) { r = v.count(); }); + } +}; + +template <class T, size_t N> +struct BenchLeftShift +{ + Duration operator()(Context& ctx) + { + const T v = make_random_bitvec<T, N>(ctx); + T r = v; + return run_bench([&](const auto i) { r <<= (i % N); }); + } +}; + +template <class T, size_t N> +struct BenchRightShift +{ + Duration operator()(Context& ctx) + { + const T v = make_random_bitvec<T, N>(ctx); + T r = v; + return run_bench([&](const auto i) { r >>= (i % N); }); + } +}; + +template <class T, size_t N> +struct BenchLeftRotate +{ + Duration operator()(Context& ctx) + { + T v = make_random_bitvec<T, N>(ctx); + return run_bench([&](const auto i) { v.rotl(i % N); }); + } +}; + +template <class T, size_t N> +struct BenchRightRotate +{ + Duration operator()(Context& ctx) + { + T v = make_random_bitvec<T, N>(ctx); + volatile bool r = false; + return run_bench([&](const auto i) { + v.rotr(i % N); + r = v.test(0); + }); + } +}; + +template <class T, size_t N> +struct BenchFindFirst +{ + Duration operator()(Context& ctx) + { + T v = make_random_bitvec<T, N>(ctx); + volatile size_t r = 0; + return run_bench([&](auto) { r = v.find_first(); }); + } +}; + +template <class T, size_t N> +struct BenchGrayCode +{ + Duration operator()(Context& ctx) + { + const T v = make_random_bitvec<T, N>(ctx); + T r = v; + + return run_bench([&](auto) { chilbert::detail::gray_code(r); }); + } +}; + +template <class T, size_t N> +struct BenchGrayCodeInv +{ + Duration operator()(Context& ctx) + { + const T v = make_random_bitvec<T, N>(ctx); + T r = v; + + return run_bench([&](auto) { chilbert::detail::gray_code_inv(r); }); + } +}; + +template <class T, size_t N> +struct BenchComparison +{ + Duration operator()(Context& ctx) + { + std::vector<T> vecs; + for (size_t i = 0; i < 32; ++i) { + vecs.emplace_back(make_random_bitvec<T, N>(ctx)); + } + + volatile bool r = false; + + return run_bench([&](const auto i) { + r |= vecs[i % vecs.size()] < vecs[(i + 1) % vecs.size()]; + }); + } +}; + +template <class T, size_t N> +struct BenchIteration +{ + Duration operator()(Context& ctx) + { + T v = make_random_bitvec<T, N>(ctx); + auto i = v.begin(); + volatile bool r = false; + return run_bench([&](const auto) { + r = (++i == v.end()); + if (r) { + i = v.begin(); + } + }); + } +}; + +/// Run benchmark for size N +template <template <class U, size_t M> class Bench, size_t N> +void +bench_row(Context& ctx, std::ostream& os) +{ + std::array<Duration, 4> results = { + ((N <= chilbert::SmallBitVec::bits_per_rack) + ? Bench<chilbert::SmallBitVec, N>{}(ctx) + : Duration{}), + Bench<chilbert::StaticBitVec<N>, N>{}(ctx), + Bench<chilbert::BoundedBitVec<N>, N>{}(ctx), + Bench<chilbert::DynamicBitVec, N>{}(ctx), + }; + + write_row(os, N, results); +} + +/// Terminate recursion +template <template <class U, size_t M> class Bench> +void +bench_rec(Context&, std::ostream&) +{ +} + +/// Run benchmark for sizes N, Ns... (recursive helper) +template <template <class U, size_t M> class Bench, size_t N, size_t... Ns> +void +bench_rec(Context& ctx, std::ostream& os) +{ + bench_row<Bench, N>(ctx, os); + bench_rec<Bench, Ns...>(ctx, os); +} + +/// Run benchmark +template <template <class U, size_t M> class Bench> +void +bench(Context& ctx, const std::string& name) +{ + std::ofstream out("bitvec_" + name + ".txt"); + out << "n\tsmall\tstatic\tbounded\tdynamic\n"; + bench_rec<Bench, 16, 32, 64, 128, 256, 512>(ctx, out); +} + +int +main() +{ + Context ctx; + + bench<BenchAnd>(ctx, "and"); + bench<BenchOr>(ctx, "or"); + bench<BenchXor>(ctx, "xor"); + bench<BenchNone>(ctx, "none"); + + bench<BenchSetOne>(ctx, "set_one"); + bench<BenchSetAll>(ctx, "set_all"); + + bench<BenchResetOne>(ctx, "reset_one"); + bench<BenchResetAll>(ctx, "reset_all"); + + bench<BenchFlipOne>(ctx, "flip_one"); + bench<BenchFlipAll>(ctx, "flip_all"); + + bench<BenchCount>(ctx, "count"); + bench<BenchFindFirst>(ctx, "find_first"); + + bench<BenchLeftShift>(ctx, "left_shift"); + bench<BenchRightShift>(ctx, "right_shift"); + + bench<BenchLeftRotate>(ctx, "left_rotate"); + bench<BenchRightRotate>(ctx, "right_rotate"); + + bench<BenchGrayCode>(ctx, "gray_code"); + bench<BenchGrayCodeInv>(ctx, "gray_code_inv"); + + bench<BenchComparison>(ctx, "comparison"); + bench<BenchIteration>(ctx, "iteration"); + + return 0; +} |