generate random numbers outside benchmark loop (#195)

This commit is contained in:
Hans Dembinski 2019-05-29 22:26:11 +02:00 committed by GitHub
parent 7e05d8ff34
commit a1c76d2b0a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 94 additions and 156 deletions

View File

@ -41,6 +41,7 @@ if (ROOT_FOUND)
target_include_directories(histogram_filling_root PRIVATE ${ROOT_INCLUDE_DIRS})
target_link_libraries(histogram_filling_root
PRIVATE ${ROOT_LIBRARIES} benchmark_main)
target_compile_options(histogram_filling_root PRIVATE -frtti -fexceptions)
# target_link_options(histogram_filling_root
# PRIVATE ${ROOT_EXE_LINKER_FLAGS})
endif()

View File

@ -6,7 +6,7 @@
#include <benchmark/benchmark.h>
#include <boost/histogram/axis.hpp>
#include "throw_exception.hpp"
#include "../test/throw_exception.hpp"
using namespace boost::histogram;

42
benchmark/generator.hpp Normal file
View File

@ -0,0 +1,42 @@
// Copyright 2019 Hans Dembinski
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <array>
#include <random>
using uniform = std::uniform_real_distribution<>;
using normal = std::normal_distribution<>;
template <class Distribution>
Distribution init();
template <>
uniform init<uniform>() {
return uniform{0.0, 1.0};
}
template <>
normal init<normal>() {
return normal{0.5, 0.3};
}
template <class Distribution, std::size_t N = 4096>
struct generator {
generator() {
std::default_random_engine rng(1);
auto dis = init<Distribution>();
std::generate(buffer_, buffer_ + N, [&] { return dis(rng); });
}
const double& operator()() {
++ptr_;
if (ptr_ == buffer_ + N) ptr_ = buffer_;
return *ptr_;
}
double buffer_[N];
const double* ptr_ = buffer_ - 1;
};

View File

@ -6,64 +6,46 @@
#include <benchmark/benchmark.h>
#include <boost/histogram/axis/regular.hpp>
#include "throw_exception.hpp"
#include <boost/histogram/storage_adaptor.hpp>
#include <boost/histogram/unlimited_storage.hpp>
#include <random>
#include "../test/throw_exception.hpp"
#include "../test/utility_histogram.hpp"
#include "generator.hpp"
#include <memory>
#include <random>
using namespace boost::histogram;
using reg = axis::regular<>;
using uniform = std::uniform_real_distribution<>;
using normal = std::normal_distribution<>;
template <class Distribution>
Distribution init();
template <>
uniform init<uniform>() {
return uniform{0.0, 1.0};
}
template <>
normal init<normal>() {
return normal{0.5, 0.3};
}
template <class Tag, class Storage, class Distribution>
static void fill_1d(benchmark::State& state) {
auto h = make_s(Tag(), Storage(), reg(100, 0, 1));
std::default_random_engine gen(1);
Distribution dis = init<Distribution>();
for (auto _ : state) benchmark::DoNotOptimize(h(dis(gen)));
auto gen = generator<Distribution>();
for (auto _ : state) benchmark::DoNotOptimize(h(gen()));
}
template <class Tag, class Storage, class Distribution>
static void fill_2d(benchmark::State& state) {
auto h = make_s(Tag(), Storage(), reg(100, 0, 1), reg(100, 0, 1));
std::default_random_engine gen(1);
Distribution dis = init<Distribution>();
for (auto _ : state) benchmark::DoNotOptimize(h(dis(gen), dis(gen)));
auto gen = generator<Distribution>();
for (auto _ : state) benchmark::DoNotOptimize(h(gen(), gen()));
}
template <class Tag, class Storage, class Distribution>
static void fill_3d(benchmark::State& state) {
auto h = make_s(Tag(), Storage(), reg(100, 0, 1), reg(100, 0, 1), reg(100, 0, 1));
std::default_random_engine gen(1);
Distribution dis = init<Distribution>();
for (auto _ : state) benchmark::DoNotOptimize(h(dis(gen), dis(gen), dis(gen)));
auto gen = generator<Distribution>();
for (auto _ : state) benchmark::DoNotOptimize(h(gen(), gen(), gen()));
}
template <class Tag, class Storage, class Distribution>
static void fill_6d(benchmark::State& state) {
auto h = make_s(Tag(), Storage(), reg(10, 0, 1), reg(10, 0, 1), reg(10, 0, 1),
reg(10, 0, 1), reg(10, 0, 1), reg(10, 0, 1));
std::default_random_engine gen(1);
Distribution dis = init<Distribution>();
auto gen = generator<Distribution>();
for (auto _ : state)
benchmark::DoNotOptimize(
h(dis(gen), dis(gen), dis(gen), dis(gen), dis(gen), dis(gen)));
benchmark::DoNotOptimize(h(gen(), gen(), gen(), gen(), gen(), gen()));
}
using SStore = std::vector<int>;

View File

@ -8,20 +8,18 @@
#include <boost/histogram/axis.hpp>
#include <boost/histogram/axis/traits.hpp>
#include <boost/histogram/detail/axes.hpp>
#include "throw_exception.hpp"
#include <boost/mp11/algorithm.hpp>
#include <random>
#include <tuple>
#include <type_traits>
#include <vector>
#include "../test/throw_exception.hpp"
#include "generator.hpp"
using namespace boost::histogram;
using reg = axis::regular<>;
using integ = axis::integer<>;
using var = axis::variable<>;
using vector_of_variant = std::vector<axis::variant<reg, integ, var>>;
using uniform = std::uniform_real_distribution<>;
using normal = std::normal_distribution<>;
template <class T, class U>
auto make_storage(const U& axes) {
@ -64,27 +62,13 @@ void fill_c(const Axes& axes, const std::size_t* strides, Storage& storage,
++storage[index];
}
template <class Distribution>
Distribution init();
template <>
uniform init<uniform>() {
return uniform{0.0, 1.0};
}
template <>
normal init<normal>() {
return normal{0.5, 0.3};
}
template <class T, class Distribution>
static void fill_1d_a(benchmark::State& state) {
auto axes = std::make_tuple(reg(100, 0, 1));
std::default_random_engine gen(1);
Distribution dis = init<Distribution>();
generator<Distribution> gen;
auto storage = make_storage<T>(axes);
for (auto _ : state) {
const auto i = std::get<0>(axes).index(dis(gen));
const auto i = std::get<0>(axes).index(gen());
++storage[i + 1];
}
}
@ -92,45 +76,41 @@ static void fill_1d_a(benchmark::State& state) {
template <class T, class Distribution>
static void fill_1d_b(benchmark::State& state) {
auto axes = std::make_tuple(reg(100, 0, 1));
std::default_random_engine gen(1);
Distribution dis = init<Distribution>();
generator<Distribution> gen;
auto storage = make_storage<T>(axes);
for (auto _ : state) { fill_b(axes, storage, std::forward_as_tuple(dis(gen))); }
for (auto _ : state) { fill_b(axes, storage, std::forward_as_tuple(gen())); }
}
template <class T, class Distribution>
static void fill_1d_c(benchmark::State& state) {
auto axes = std::make_tuple(reg(100, 0, 1));
std::default_random_engine gen(1);
Distribution dis = init<Distribution>();
generator<Distribution> gen;
auto storage = make_storage<T>(axes);
auto strides = make_strides(axes);
for (auto _ : state) {
fill_c(axes, strides.data(), storage, std::forward_as_tuple(dis(gen)));
fill_c(axes, strides.data(), storage, std::forward_as_tuple(gen()));
}
}
template <class T, class Distribution>
static void fill_1d_c_dyn(benchmark::State& state) {
auto axes = vector_of_variant({reg(100, 0, 1)});
std::default_random_engine gen(1);
Distribution dis = init<Distribution>();
generator<Distribution> gen;
auto storage = make_storage<T>(axes);
auto strides = make_strides(axes);
for (auto _ : state) {
fill_c(axes, strides.data(), storage, std::forward_as_tuple(dis(gen)));
fill_c(axes, strides.data(), storage, std::forward_as_tuple(gen()));
}
}
template <class T, class Distribution>
static void fill_2d_a(benchmark::State& state) {
auto axes = std::make_tuple(reg(100, 0, 1), reg(100, 0, 1));
std::default_random_engine gen(1);
Distribution dis = init<Distribution>();
generator<Distribution> gen;
auto storage = make_storage<T>(axes);
for (auto _ : state) {
const auto i0 = std::get<0>(axes).index(dis(gen));
const auto i1 = std::get<1>(axes).index(dis(gen));
const auto i0 = std::get<0>(axes).index(gen());
const auto i1 = std::get<1>(axes).index(gen());
const auto stride = axis::traits::extent(std::get<0>(axes));
++storage[(i0 + 1) * stride + (i1 + 1)];
}
@ -139,41 +119,36 @@ static void fill_2d_a(benchmark::State& state) {
template <class T, class Distribution>
static void fill_2d_b(benchmark::State& state) {
auto axes = std::make_tuple(reg(100, 0, 1), reg(100, 0, 1));
std::default_random_engine gen(1);
Distribution dis = init<Distribution>();
generator<Distribution> gen;
auto storage = make_storage<T>(axes);
for (auto _ : state) {
fill_b(axes, storage, std::forward_as_tuple(dis(gen), dis(gen)));
}
for (auto _ : state) { fill_b(axes, storage, std::forward_as_tuple(gen(), gen())); }
}
template <class T, class Distribution>
static void fill_2d_c(benchmark::State& state) {
auto axes = std::make_tuple(reg(100, 0, 1), reg(100, 0, 1));
std::default_random_engine gen(1);
Distribution dis = init<Distribution>();
generator<Distribution> gen;
auto storage = make_storage<T>(axes);
auto strides = make_strides(axes);
assert(strides.size() == 3);
assert(strides[0] == 1);
assert(strides[1] == 102);
for (auto _ : state) {
fill_c(axes, strides.data(), storage, std::forward_as_tuple(dis(gen), dis(gen)));
fill_c(axes, strides.data(), storage, std::forward_as_tuple(gen(), gen()));
}
}
template <class T, class Distribution>
static void fill_2d_c_dyn(benchmark::State& state) {
auto axes = vector_of_variant({reg(100, 0, 1), reg(100, 0, 1)});
std::default_random_engine gen(1);
Distribution dis = init<Distribution>();
generator<Distribution> gen;
auto storage = make_storage<T>(axes);
auto strides = make_strides(axes);
assert(strides.size() == 3);
assert(strides[0] == 1);
assert(strides[1] == 102);
for (auto _ : state) {
fill_c(axes, strides.data(), storage, std::forward_as_tuple(dis(gen), dis(gen)));
fill_c(axes, strides.data(), storage, std::forward_as_tuple(gen(), gen()));
}
}

View File

@ -5,36 +5,17 @@
// or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <benchmark/benchmark.h>
#include <random>
#include "throw_exception.hpp"
#include <gsl/gsl_histogram.h>
#include <gsl/gsl_histogram2d.h>
using uniform = std::uniform_real_distribution<>;
using normal = std::normal_distribution<>;
template <class Distribution>
Distribution init();
template <>
uniform init<uniform>() {
return uniform{0.0, 1.0};
}
template <>
normal init<normal>() {
return normal{0.5, 0.3};
}
#include "../test/throw_exception.hpp"
#include "generator.hpp"
template <class Distribution>
static void fill_1d(benchmark::State& state) {
gsl_histogram* h = gsl_histogram_alloc(100);
gsl_histogram_set_ranges_uniform(h, 0, 1);
std::default_random_engine gen(1);
Distribution dis = init<Distribution>();
for (auto _ : state) benchmark::DoNotOptimize(gsl_histogram_increment(h, dis(gen)));
generator<Distribution> gen;
for (auto _ : state) benchmark::DoNotOptimize(gsl_histogram_increment(h, gen()));
gsl_histogram_free(h);
}
@ -42,10 +23,9 @@ template <class Distribution>
static void fill_2d(benchmark::State& state) {
gsl_histogram2d* h = gsl_histogram2d_alloc(100, 100);
gsl_histogram2d_set_ranges_uniform(h, 0, 1, 0, 1);
std::default_random_engine gen(1);
Distribution dis = init<Distribution>();
generator<Distribution> gen;
for (auto _ : state)
benchmark::DoNotOptimize(gsl_histogram2d_increment(h, dis(gen), dis(gen)));
benchmark::DoNotOptimize(gsl_histogram2d_increment(h, gen(), gen()));
gsl_histogram2d_free(h);
}

View File

@ -4,52 +4,32 @@
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <benchmark/benchmark.h>
#include <random>
#include <TH1I.h>
#include <TH2I.h>
#include <TH3I.h>
#include <THn.h>
using uniform = std::uniform_real_distribution<>;
using normal = std::normal_distribution<>;
template <class Distribution>
Distribution init();
template <>
uniform init<uniform>() {
return uniform{0.0, 1.0};
}
template <>
normal init<normal>() {
return normal{0.5, 0.3};
}
#include <benchmark/benchmark.h>
#include "generator.hpp"
template <class Distribution>
static void fill_1d(benchmark::State& state) {
TH1I h("", "", 100, 0, 1);
std::default_random_engine gen(1);
Distribution dis = init<Distribution>();
for (auto _ : state) benchmark::DoNotOptimize(h.Fill(dis(gen)));
generator<Distribution> gen;
for (auto _ : state) benchmark::DoNotOptimize(h.Fill(gen()));
}
template <class Distribution>
static void fill_2d(benchmark::State& state) {
TH2I h("", "", 100, 0, 1, 100, 0, 1);
std::default_random_engine gen(1);
Distribution dis = init<Distribution>();
for (auto _ : state) benchmark::DoNotOptimize(h.Fill(dis(gen), dis(gen)));
generator<Distribution> gen;
for (auto _ : state) benchmark::DoNotOptimize(h.Fill(gen(), gen()));
}
template <class Distribution>
static void fill_3d(benchmark::State& state) {
TH3I h("", "", 100, 0, 1, 100, 0, 1, 100, 0, 1);
std::default_random_engine gen(1);
Distribution dis = init<Distribution>();
for (auto _ : state) benchmark::DoNotOptimize(h.Fill(dis(gen), dis(gen), dis(gen)));
generator<Distribution> gen;
for (auto _ : state) benchmark::DoNotOptimize(h.Fill(gen(), gen(), gen()));
}
template <class Distribution>
@ -58,10 +38,9 @@ static void fill_6d(benchmark::State& state) {
double min[] = {0, 0, 0, 0, 0, 0};
double max[] = {1, 1, 1, 1, 1, 1};
THnI h("", "", 6, bin, min, max);
std::default_random_engine gen(1);
Distribution dis = init<Distribution>();
generator<Distribution> gen;
for (auto _ : state) {
const double buf[6] = {dis(gen), dis(gen), dis(gen), dis(gen), dis(gen), dis(gen)};
const double buf[6] = {gen(), gen(), gen(), gen(), gen(), gen()};
benchmark::DoNotOptimize(h.Fill(buf));
}
}

View File

@ -7,13 +7,13 @@
#include <benchmark/benchmark.h>
#include <boost/histogram/axis/integer.hpp>
#include <boost/histogram/axis/regular.hpp>
#include "throw_exception.hpp"
#include <boost/histogram/histogram.hpp>
#include <boost/histogram/indexed.hpp>
#include <boost/histogram/literals.hpp>
#include <boost/histogram/make_histogram.hpp>
#include <boost/mp11/integral.hpp>
#include <vector>
#include "../test/throw_exception.hpp"
using namespace boost::histogram;
using namespace boost::histogram::literals;

View File

@ -7,7 +7,6 @@
#include <benchmark/benchmark.h>
#include <boost/histogram/accumulators/thread_safe.hpp>
#include <boost/histogram/axis/regular.hpp>
#include "throw_exception.hpp"
#include <boost/histogram/histogram.hpp>
#include <boost/histogram/make_histogram.hpp>
#include <chrono>
@ -17,6 +16,7 @@
#include <random>
#include <thread>
#include <vector>
#include "../test/throw_exception.hpp"
using namespace boost::histogram;
using namespace std::chrono_literals;

View File

@ -1,21 +0,0 @@
// Copyright 2019 Hans Dembinski
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifdef BOOST_NO_EXCEPTIONS
#include <cstdlib> // std::abort
#include <exception>
#include <iostream>
namespace boost {
// dummy implementation for user-defined function from boost/throw_exception.hpp
inline void throw_exception(std::exception const& e) {
std::cerr << e.what() << std::endl;
std::abort();
}
} // namespace boost
#endif