14#include <benchmark/benchmark.h>
22using namespace benchmark;
30class PippengerBench :
public benchmark::Fixture {
32 static constexpr size_t MAX_POINTS = 1 << 21;
34 std::vector<Fr> scalars;
37 void SetUp([[maybe_unused]] const ::benchmark::State& state)
override
40 srs = bb::srs::get_crs_factory<Curve>()->get_crs(MAX_POINTS);
42 scalars.resize(MAX_POINTS);
43 for (
auto& x : scalars) {
51BENCHMARK_DEFINE_F(PippengerBench, PippengerUnsafe)(benchmark::State& state)
53 const size_t num_points =
static_cast<size_t>(state.range(0));
58 for (
auto _ : state) {
60 bb::scalar_multiplication::pippenger_unsafe<Curve>(poly_scalars, points);
66BENCHMARK_DEFINE_F(PippengerBench, PippengerRoundParallel)(benchmark::State& state)
68 const size_t num_threads =
static_cast<size_t>(state.range(0));
69 const size_t num_points =
static_cast<size_t>(state.range(1));
77 for (
auto _ : state) {
79 bb::scalar_multiplication::pippenger_round_parallel<Curve>(poly_scalars, points);
85BENCHMARK_DEFINE_F(PippengerBench, PippengerUnsafeThreads)(benchmark::State& state)
87 const size_t num_threads =
static_cast<size_t>(state.range(0));
88 const size_t num_points =
static_cast<size_t>(state.range(1));
96 for (
auto _ : state) {
98 bb::scalar_multiplication::pippenger_unsafe<Curve>(poly_scalars, points);
113BENCHMARK_DEFINE_F(PippengerBench, PippengerRoundParallelScaling)(benchmark::State& state)
115 const size_t num_points =
static_cast<size_t>(state.range(0));
120 for (
auto _ : state) {
122 bb::scalar_multiplication::pippenger_round_parallel<Curve>(poly_scalars, points);
130BENCHMARK_DEFINE_F(PippengerBench, PippengerScalingLegacy)(benchmark::State& state)
132 const size_t num_points =
static_cast<size_t>(state.range(0));
137 for (
auto _ : state) {
139 bb::scalar_multiplication::legacy::pippenger_unsafe<Curve>(poly_scalars, points);
145BENCHMARK_DEFINE_F(PippengerBench, BatchMSM)(benchmark::State& state)
147 const size_t num_polys =
static_cast<size_t>(state.range(0));
148 const size_t poly_size =
static_cast<size_t>(state.range(1));
154 for (
size_t i = 0; i < num_polys; ++i) {
155 all_scalars[i].resize(poly_size);
156 for (
auto& s : all_scalars[i]) {
162 for (
auto _ : state) {
172 return static_cast<double>(
engine.get_random_uint32()) /
static_cast<double>(std::numeric_limits<uint32_t>::max());
195enum class SparsityProfile : uint8_t { Dense80 = 0, DupHeavy = 1 };
199 std::vector<Fr>
out(n);
200 if (profile == SparsityProfile::Dense80) {
201 for (
size_t i = 0; i < n; ++i) {
207 for (
size_t i = 0; i < n; ++i) {
208 const double r = uniform01(
engine);
211 }
else if (r < 0.45) {
213 }
else if (r < 0.50) {
224BENCHMARK_DEFINE_F(PippengerBench, PippengerSparsity)(benchmark::State& state)
226 const auto profile =
static_cast<SparsityProfile
>(state.range(0));
227 const size_t num_points =
static_cast<size_t>(state.range(1));
228 const bool dedup_hint = (profile == SparsityProfile::DupHeavy);
229 state.SetLabel(profile == SparsityProfile::Dense80 ?
"Dense80" :
"DupHeavy");
243 std::vector<Fr> msm_scalars = build_sparsity_scalars(profile, num_points, case_engine);
247 for (
auto _ : state) {
249 (void)bb::scalar_multiplication::pippenger_round_parallel<Curve>(poly_scalars, points, dedup_hint);
256BENCHMARK_REGISTER_F(PippengerBench, PippengerUnsafe)
257 ->Unit(benchmark::kMillisecond)
259 ->Range(1 << 14, 1 << 20);
262BENCHMARK_REGISTER_F(PippengerBench, PippengerSparsity)
263 ->Unit(benchmark::kMillisecond)
264 ->ArgsProduct({ { 0, 1 }, { 1 << 15, 1 << 16, 1 << 17, 1 << 18, 1 << 19 } });
268BENCHMARK_REGISTER_F(PippengerBench, BatchMSM)
269 ->Unit(benchmark::kMillisecond)
270 ->Args({ 32, 1 << 19 })
271 ->Args({ 32, 1 << 21 });
275BENCHMARK_REGISTER_F(PippengerBench, PippengerRoundParallel)
276 ->Unit(benchmark::kMillisecond)
277 ->ArgsProduct({ { 1, 4, 8, 12, 16, 32, 64, 128 },
299BENCHMARK_REGISTER_F(PippengerBench, PippengerRoundParallelScaling)
300 ->Unit(benchmark::kMillisecond)
307BENCHMARK_REGISTER_F(PippengerBench, PippengerScalingLegacy)
308 ->Unit(benchmark::kMillisecond)
315BENCHMARK_REGISTER_F(PippengerBench, PippengerUnsafeThreads)
316 ->Unit(benchmark::kMillisecond)
317 ->ArgsProduct({ { 1, 4, 8, 12, 16, 32, 64, 128 },
typename Group::affine_element AffineElement
static std::vector< AffineElement > batch_multi_scalar_mul(std::span< const AffineElement > points, std::span< PolynomialSpan< ScalarField > > scalars, bool handle_edge_cases=true, std::span< const uint32_t > dedup_infos={}) noexcept
#define GOOGLE_BB_BENCH_REPORTER(state)
RNG & get_debug_randomness(bool reset, std::uint_fast64_t seed)
std::filesystem::path bb_crs_path()
void init_file_crs_factory(const std::filesystem::path &path)
void set_parallel_for_concurrency(size_t num_cores)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
bb::VectorAffineElementPushSpan< BaseParams > out
static field random_element(numeric::RNG *engine=nullptr) noexcept
static constexpr field zero()