aboutsummaryrefslogtreecommitdiffstats
path: root/benchmark/bench_bitvec.cpp
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2022-09-16 15:39:48 -0400
committerDavid Robillard <d@drobilla.net>2022-09-16 22:31:06 -0400
commit49dab5622b31421eb6af84eae376d73fae1cd4a0 (patch)
tree86290707551320ab35952bccc11c66df05714b26 /benchmark/bench_bitvec.cpp
parent342a22b6d75597ee22c195b60607402e3ed028b2 (diff)
downloadchilbert-49dab5622b31421eb6af84eae376d73fae1cd4a0.tar.gz
chilbert-49dab5622b31421eb6af84eae376d73fae1cd4a0.tar.bz2
chilbert-49dab5622b31421eb6af84eae376d73fae1cd4a0.zip
Switch to meson build system
Diffstat (limited to 'benchmark/bench_bitvec.cpp')
-rw-r--r--benchmark/bench_bitvec.cpp352
1 files changed, 352 insertions, 0 deletions
diff --git a/benchmark/bench_bitvec.cpp b/benchmark/bench_bitvec.cpp
new file mode 100644
index 0000000..6580af9
--- /dev/null
+++ b/benchmark/bench_bitvec.cpp
@@ -0,0 +1,352 @@
+/*
+ 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 "test_utils.hpp"
+
+#include "chilbert/BoundedBitVec.hpp" // IWYU pragma: keep
+#include "chilbert/DynamicBitVec.hpp" // IWYU pragma: keep
+#include "chilbert/SmallBitVec.hpp"
+#include "chilbert/StaticBitVec.hpp" // IWYU pragma: keep
+
+#include <array>
+#include <cstddef>
+#include <fstream>
+#include <string>
+#include <vector>
+
+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;
+ (void)r;
+
+ 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;
+ (void)r;
+
+ 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;
+ (void)r;
+
+ 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;
+ (void)r;
+
+ 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;
+}