/* 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 "chilbert/chilbert.hpp" #include <array> #include <cstddef> #include <fstream> #include <string> template<class H, size_t M, size_t D> struct BenchCoordsToIndex { Duration operator()(Context& ctx) { const auto p = make_random_point<M, D>(ctx); H ha = make_zero_bitvec<H, D * M>(); return run_bench([&](auto) { chilbert::coords_to_index(p, M, D, ha); }); } }; template<class H, size_t M, size_t D> struct BenchIndexToCoords { Duration operator()(Context& ctx) { auto p = make_random_point<M, D>(ctx); const H ha = make_random_bitvec<H, D * M>(ctx); return run_bench([&](auto) { chilbert::index_to_coords(p, M, D, ha); }); } }; /// Run benchmark for size N template<template<class H, size_t M, size_t D> class Bench, size_t M, size_t D> void bench_row(Context& ctx, std::ostream& os) { std::array<Duration, 4> results = { ((M * D <= chilbert::SmallBitVec::bits_per_rack) ? Bench<chilbert::SmallBitVec, M, D>{}(ctx) : Duration{}), Bench<chilbert::StaticBitVec<M * D>, M, D>{}(ctx), Bench<chilbert::BoundedBitVec<M * D>, M, D>{}(ctx), Bench<chilbert::DynamicBitVec, M, D>{}(ctx), }; write_row(os, D, results); } /// Terminate recursion template<template<class H, size_t M, size_t D> class Bench, size_t M> void bench_rec(Context&, std::ostream&) {} /// Run benchmark for sizes N, Ns... (recursive helper) template<template<class H, size_t M, size_t D> class Bench, size_t M, size_t D, size_t... Ds> void bench_rec(Context& ctx, std::ostream& os) { bench_row<Bench, M, D>(ctx, os); bench_rec<Bench, M, Ds...>(ctx, os); } /// Run benchmark template<template<class H, size_t M, size_t D> class Bench> void bench(Context& ctx, const std::string& name) { std::ofstream out("hilbert_" + name + ".txt"); out << "d\tsmall\tstatic\tbounded\tdynamic\n"; bench_rec<Bench, 8, 2, 4, 8, 16, 32, 64>(ctx, out); } int main() { Context ctx; bench<BenchCoordsToIndex>(ctx, "coords_to_index"); bench<BenchIndexToCoords>(ctx, "index_to_coords"); return 0; }