/* * Copyright Nick Thompson, 2020 * Use, modification and distribution are subject to 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 #include #include #include #include #include #include #include #include double exponential(benchmark::IterationCount j) { return std::pow(2, j); } template void DyadicGrid(benchmark::State & state) { int j = state.range(0); size_t s = 0; for (auto _ : state) { auto v = boost::math::daubechies_scaling_dyadic_grid(j); benchmark::DoNotOptimize(v[0]); s = v.size(); } state.counters["RAM"] = s*sizeof(Real); state.SetComplexityN(state.range(0)); } BENCHMARK_TEMPLATE(DyadicGrid, double, 4)->DenseRange(3, 22, 1)->Unit(benchmark::kMillisecond)->Complexity(exponential); //BENCHMARK_TEMPLATE(DyadicGrid, double, 8)->DenseRange(3, 22, 1)->Unit(benchmark::kMillisecond)->Complexity(exponential); //BENCHMARK_TEMPLATE(DyadicGrid, double, 11)->DenseRange(3,22,1)->Unit(benchmark::kMillisecond)->Complexity(exponential); uint64_t s[2] = { 0x41, 0x29837592 }; static inline uint64_t rotl(const uint64_t x, int k) { return (x << k) | (x >> (64 - k)); } uint64_t next(void) { const uint64_t s0 = s[0]; uint64_t s1 = s[1]; const uint64_t result = s0 + s1; s1 ^= s0; s[0] = rotl(s0, 55) ^ s1 ^ (s1 << 14); // a, b s[1] = rotl(s1, 36); // c return result; } double uniform() { return next()*(1.0/18446744073709551616.0); } template void ScalingEvaluation(benchmark::State & state) { auto phi = boost::math::daubechies_scaling(); Real x = 0; Real step = std::numeric_limits::epsilon(); for (auto _ : state) { benchmark::DoNotOptimize(phi(x)); x += step; } } BENCHMARK_TEMPLATE(ScalingEvaluation, double, 2); BENCHMARK_TEMPLATE(ScalingEvaluation, double, 3); BENCHMARK_TEMPLATE(ScalingEvaluation, double, 4); BENCHMARK_TEMPLATE(ScalingEvaluation, double, 5); BENCHMARK_TEMPLATE(ScalingEvaluation, double, 6); BENCHMARK_TEMPLATE(ScalingEvaluation, double, 7); BENCHMARK_TEMPLATE(ScalingEvaluation, double, 8); BENCHMARK_TEMPLATE(ScalingEvaluation, double, 9); BENCHMARK_TEMPLATE(ScalingEvaluation, double, 10); BENCHMARK_TEMPLATE(ScalingEvaluation, double, 11); BENCHMARK_TEMPLATE(ScalingEvaluation, double, 12); BENCHMARK_TEMPLATE(ScalingEvaluation, double, 13); BENCHMARK_TEMPLATE(ScalingEvaluation, double, 14); BENCHMARK_TEMPLATE(ScalingEvaluation, double, 15); BENCHMARK_TEMPLATE(ScalingEvaluation, float, 2); BENCHMARK_TEMPLATE(ScalingEvaluation, float, 3); BENCHMARK_TEMPLATE(ScalingEvaluation, float, 4); BENCHMARK_TEMPLATE(ScalingEvaluation, float, 5); BENCHMARK_TEMPLATE(ScalingEvaluation, float, 6); BENCHMARK_TEMPLATE(ScalingEvaluation, float, 7); BENCHMARK_TEMPLATE(ScalingEvaluation, float, 8); BENCHMARK_TEMPLATE(ScalingEvaluation, float, 9); BENCHMARK_TEMPLATE(ScalingEvaluation, float, 10); BENCHMARK_TEMPLATE(ScalingEvaluation, float, 11); BENCHMARK_TEMPLATE(ScalingEvaluation, float, 12); BENCHMARK_TEMPLATE(ScalingEvaluation, float, 13); BENCHMARK_TEMPLATE(ScalingEvaluation, float, 14); BENCHMARK_TEMPLATE(ScalingEvaluation, float, 15); template void ScalingConstructor(benchmark::State & state) { for (auto _ : state) { benchmark::DoNotOptimize(boost::math::daubechies_scaling()); } } BENCHMARK_TEMPLATE(ScalingConstructor, float, 2)->Unit(benchmark::kMillisecond); BENCHMARK_TEMPLATE(ScalingConstructor, double, 2)->Unit(benchmark::kMillisecond); BENCHMARK_TEMPLATE(ScalingConstructor, long double, 2)->Unit(benchmark::kMillisecond); BENCHMARK_TEMPLATE(ScalingConstructor, float, 3)->Unit(benchmark::kMillisecond); BENCHMARK_TEMPLATE(ScalingConstructor, double, 3)->Unit(benchmark::kMillisecond); BENCHMARK_TEMPLATE(ScalingConstructor, long double, 3)->Unit(benchmark::kMillisecond); BENCHMARK_TEMPLATE(ScalingConstructor, float, 4)->Unit(benchmark::kMillisecond); BENCHMARK_TEMPLATE(ScalingConstructor, double, 4)->Unit(benchmark::kMillisecond); BENCHMARK_TEMPLATE(ScalingConstructor, long double, 4)->Unit(benchmark::kMillisecond); BENCHMARK_TEMPLATE(ScalingConstructor, float, 5)->Unit(benchmark::kMillisecond); BENCHMARK_TEMPLATE(ScalingConstructor, double, 5)->Unit(benchmark::kMillisecond); BENCHMARK_TEMPLATE(ScalingConstructor, long double, 5)->Unit(benchmark::kMillisecond); BENCHMARK_TEMPLATE(ScalingConstructor, float, 11)->Unit(benchmark::kMillisecond); BENCHMARK_TEMPLATE(ScalingConstructor, double, 11)->Unit(benchmark::kMillisecond); BENCHMARK_TEMPLATE(ScalingConstructor, long double, 11)->Unit(benchmark::kMillisecond); template void CubicHermite(benchmark::State & state) { using boost::math::interpolators::cubic_hermite; auto n = state.range(0); std::vector x(n); std::vector y(n); std::vector dydx(n); std::random_device rd; boost::random::uniform_real_distribution dis(Real(0), Real(1)); x[0] = dis(rd); y[0] = dis(rd); dydx[0] = dis(rd); for (size_t i = 1; i < y.size(); ++i) { x[i] = x[i-1] + dis(rd); y[i] = dis(rd); dydx[i] = dis(rd); } Real x0 = x.front(); Real xf = x.back(); auto qh = cubic_hermite(std::move(x), std::move(y), std::move(dydx)); Real t = x0; Real step = uniform()*(xf-x0)/2048; for (auto _ : state) { benchmark::DoNotOptimize(qh(t)); t += step; if (t >= xf) { t = x0; step = uniform()*(xf-x0)/2048; } } state.SetComplexityN(state.range(0)); } BENCHMARK_TEMPLATE(CubicHermite, double)->RangeMultiplier(2)->Range(1<<8, 1<<20)->Complexity(benchmark::oLogN); template void CardinalCubicHermite(benchmark::State & state) { using boost::math::interpolators::detail::cardinal_cubic_hermite_detail; auto n = state.range(0); std::vector y(n); std::vector dydx(n); std::random_device rd; boost::random::uniform_real_distribution dis(Real(0), Real(1)); for (size_t i = 0; i < y.size(); ++i) { y[i] = uniform(); dydx[i] = uniform(); } Real dx = Real(1)/Real(8); Real x0 = 0; Real xf = x0 + (y.size()-1)*dx; auto qh = cardinal_cubic_hermite_detail(std::move(y), std::move(dydx), x0, dx); Real x = x0; Real step = uniform()*(xf-x0)/2048; for (auto _ : state) { benchmark::DoNotOptimize(qh.unchecked_evaluation(x)); x += step; if (x >= xf) { x = x0; step = uniform()*(xf-x0)/2048; } } state.SetComplexityN(state.range(0)); } template void CardinalCubicHermiteAOS(benchmark::State & state) { auto n = state.range(0); std::vector> dat(n); std::random_device rd; boost::random::uniform_real_distribution dis(Real(0), Real(1)); for (size_t i = 0; i < dat.size(); ++i) { dat[i][0] = uniform(); dat[i][1] = uniform(); } using boost::math::interpolators::detail::cardinal_cubic_hermite_detail_aos; Real dx = Real(1)/Real(8); Real x0 = 0; Real xf = x0 + (dat.size()-1)*dx; auto qh = cardinal_cubic_hermite_detail_aos(std::move(dat), x0, dx); Real x = 0; Real step = uniform()*(xf-x0)/2048; for (auto _ : state) { benchmark::DoNotOptimize(qh.unchecked_evaluation(x)); x += step; if (x >= xf) { x = x0; step = uniform()*(xf-x0)/2048; } } state.SetComplexityN(state.range(0)); } BENCHMARK_TEMPLATE(CardinalCubicHermiteAOS, double)->RangeMultiplier(2)->Range(1<<8, 1<<21)->Complexity(benchmark::o1); BENCHMARK_TEMPLATE(CardinalCubicHermite, double)->RangeMultiplier(2)->Range(1<<8, 1<<21)->Complexity(benchmark::o1); template void SineEvaluation(benchmark::State& state) { std::default_random_engine gen; std::uniform_real_distribution x_dis(0, 3.14159); Real x = x_dis(gen); for (auto _ : state) { benchmark::DoNotOptimize(std::sin(x)); x += std::numeric_limits::epsilon(); } } BENCHMARK_TEMPLATE(SineEvaluation, float); BENCHMARK_TEMPLATE(SineEvaluation, double); BENCHMARK_TEMPLATE(SineEvaluation, long double); template void ExpEvaluation(benchmark::State& state) { std::default_random_engine gen; std::uniform_real_distribution x_dis(0, 3.14159); Real x = x_dis(gen); for (auto _ : state) { benchmark::DoNotOptimize(std::exp(x)); x += std::numeric_limits::epsilon(); } } BENCHMARK_TEMPLATE(ExpEvaluation, float); BENCHMARK_TEMPLATE(ExpEvaluation, double); BENCHMARK_TEMPLATE(ExpEvaluation, long double); template void PowEvaluation(benchmark::State& state) { std::default_random_engine gen; std::uniform_real_distribution x_dis(0, 3.14159); Real x = x_dis(gen); for (auto _ : state) { benchmark::DoNotOptimize(std::pow(x, x+1)); x += std::numeric_limits::epsilon(); } } BENCHMARK_TEMPLATE(PowEvaluation, float); BENCHMARK_TEMPLATE(PowEvaluation, double); BENCHMARK_TEMPLATE(PowEvaluation, long double); template void CardinalQuinticHermite(benchmark::State & state) { using boost::math::interpolators::detail::cardinal_quintic_hermite_detail; auto n = state.range(0); std::vector y(n); std::vector dydx(n); std::vector d2ydx2(n); std::random_device rd; boost::random::uniform_real_distribution dis(Real(0), Real(1)); for (size_t i = 0; i < y.size(); ++i) { y[i] = uniform(); dydx[i] = uniform(); d2ydx2[i] = uniform(); } Real dx = Real(1)/Real(8); Real x0 = 0; Real xf = x0 + (y.size()-1)*dx; auto qh = cardinal_quintic_hermite_detail(std::move(y), std::move(dydx), std::move(d2ydx2), x0, dx); Real x = 0; Real step = uniform()*(xf-x0)/2048; for (auto _ : state) { benchmark::DoNotOptimize(qh.unchecked_evaluation(x)); x += step; if (x >= xf) { x = x0; step = uniform()*(xf-x0)/2048; } } state.SetComplexityN(state.range(0)); } template void CardinalQuinticHermiteAOS(benchmark::State & state) { auto n = state.range(0); std::vector> dat(n); std::random_device rd; boost::random::uniform_real_distribution dis(Real(0), Real(1)); for (size_t i = 0; i < dat.size(); ++i) { dat[i][0] = uniform(); dat[i][1] = uniform(); dat[i][2] = uniform(); } using boost::math::interpolators::detail::cardinal_quintic_hermite_detail_aos; Real dx = Real(1)/Real(8); Real x0 = 0; Real xf = x0 + (dat.size()-1)*dx; auto qh = cardinal_quintic_hermite_detail_aos(std::move(dat), x0, dx); Real x = x0; Real step = uniform()*(xf-x0)/2048; for (auto _ : state) { benchmark::DoNotOptimize(qh.unchecked_evaluation(x)); x += step; if (x >= xf) { x = x0; step = uniform()*(xf-x0)/2048; } } state.SetComplexityN(state.range(0)); } BENCHMARK_TEMPLATE(CardinalQuinticHermiteAOS, double)->RangeMultiplier(2)->Range(1<<8, 1<<22)->Complexity(benchmark::o1); BENCHMARK_TEMPLATE(CardinalQuinticHermite, double)->RangeMultiplier(2)->Range(1<<8, 1<<22)->Complexity(benchmark::o1); template void SepticHermite(benchmark::State & state) { using boost::math::interpolators::detail::septic_hermite_detail; auto n = state.range(0); std::vector x(n); std::vector y(n); std::vector dydx(n); std::vector d2ydx2(n); std::vector d3ydx3(n); std::random_device rd; boost::random::uniform_real_distribution dis(Real(0), Real(1)); Real x0 = dis(rd); x[0] = x0; for (decltype(n) i = 1; i < n; ++i) { x[i] = x[i-1] + dis(rd); } for (size_t i = 0; i < y.size(); ++i) { y[i] = dis(rd); dydx[i] = dis(rd); d2ydx2[i] = dis(rd); d3ydx3[i] = dis(rd); } Real xf = x.back(); auto sh = septic_hermite_detail(std::move(x), std::move(y), std::move(dydx), std::move(d2ydx2), std::move(d3ydx3)); Real t = x0; for (auto _ : state) { benchmark::DoNotOptimize(sh(t)); t += xf/128; if (t >= xf) { t = x0; } } state.SetComplexityN(state.range(0)); } BENCHMARK_TEMPLATE(SepticHermite, double)->RangeMultiplier(2)->Range(1<<8, 1<<20)->Complexity(); template void CardinalSepticHermite(benchmark::State & state) { using boost::math::interpolators::detail::cardinal_septic_hermite_detail; auto n = state.range(0); std::vector y(n); std::vector dydx(n); std::vector d2ydx2(n); std::vector d3ydx3(n); std::random_device rd; boost::random::uniform_real_distribution dis(Real(0), Real(1)); for (size_t i = 0; i < y.size(); ++i) { y[i] = dis(rd); dydx[i] = dis(rd); d2ydx2[i] = dis(rd); d3ydx3[i] = dis(rd); } Real dx = Real(1)/Real(8); Real x0 = 0; Real xf = x0 + (y.size()-1)*dx; auto sh = cardinal_septic_hermite_detail(std::move(y), std::move(dydx), std::move(d2ydx2), std::move(d3ydx3), x0, dx); Real x = 0; for (auto _ : state) { benchmark::DoNotOptimize(sh.unchecked_evaluation(x)); x += xf/128; if (x >= xf) { x = x0; } } state.SetComplexityN(state.range(0)); } BENCHMARK_TEMPLATE(CardinalSepticHermite, double)->RangeMultiplier(2)->Range(1<<8, 1<<20)->Complexity(); template void CardinalSepticHermiteAOS(benchmark::State & state) { using boost::math::interpolators::detail::cardinal_septic_hermite_detail_aos; auto n = state.range(0); std::vector> data(n); std::random_device rd; boost::random::uniform_real_distribution dis(Real(0), Real(1)); for (size_t i = 0; i < data.size(); ++i) { for (size_t j = 0; j < 4; ++j) { data[i][j] = dis(rd); } } Real dx = Real(1)/Real(8); Real x0 = 0; Real xf = x0 + (data.size()-1)*dx; auto sh = cardinal_septic_hermite_detail_aos(std::move(data), x0, dx); Real x = 0; for (auto _ : state) { benchmark::DoNotOptimize(sh.unchecked_evaluation(x)); x += xf/128; if (x >= xf) { x = x0; } } state.SetComplexityN(state.range(0)); } BENCHMARK_TEMPLATE(CardinalSepticHermiteAOS, double)->RangeMultiplier(2)->Range(1<<8, 1<<20)->Complexity(); template void WaveletTransform(benchmark::State & state) { auto psi = boost::math::daubechies_wavelet(); auto f = [](Real t) { return std::exp(-t*t); }; auto Wf = boost::math::quadrature::daubechies_wavelet_transform(f, psi); for (auto _ : state) { Real s = 1 + uniform(); Real t = uniform(); benchmark::DoNotOptimize(Wf(s, t)); } } BENCHMARK_TEMPLATE(WaveletTransform, float, 3); BENCHMARK_TEMPLATE(WaveletTransform, float, 4); BENCHMARK_TEMPLATE(WaveletTransform, float, 5); BENCHMARK_TEMPLATE(WaveletTransform, float, 6); BENCHMARK_TEMPLATE(WaveletTransform, float, 7); BENCHMARK_TEMPLATE(WaveletTransform, float, 8); BENCHMARK_TEMPLATE(WaveletTransform, float, 9); BENCHMARK_TEMPLATE(WaveletTransform, float, 10); BENCHMARK_TEMPLATE(WaveletTransform, float, 11); BENCHMARK_TEMPLATE(WaveletTransform, float, 12); BENCHMARK_TEMPLATE(WaveletTransform, float, 13); BENCHMARK_TEMPLATE(WaveletTransform, float, 14); BENCHMARK_TEMPLATE(WaveletTransform, float, 15); BENCHMARK_TEMPLATE(WaveletTransform, float, 16); BENCHMARK_TEMPLATE(WaveletTransform, float, 17); BENCHMARK_TEMPLATE(WaveletTransform, float, 18); BENCHMARK_TEMPLATE(WaveletTransform, float, 19); BENCHMARK_TEMPLATE(WaveletTransform, double, 4); BENCHMARK_TEMPLATE(WaveletTransform, double, 8); BENCHMARK_TEMPLATE(WaveletTransform, double, 12); BENCHMARK_TEMPLATE(WaveletTransform, double, 15); BENCHMARK_TEMPLATE(WaveletTransform, double, 19); BENCHMARK_MAIN();