Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: benchmark Protogalaxy rounds #4316

Merged
merged 33 commits into from
Feb 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
fa71a6d
Create initial benchmark file.
codygunton Jan 29, 2024
61d55ed
Roundify with captuers
codygunton Jan 29, 2024
edc44f4
Add executable
codygunton Jan 30, 2024
35e628f
Further roundification
codygunton Jan 30, 2024
da88d44
Fix after reset to master and cherry picking.
codygunton Jan 31, 2024
8975eb6
Folding rounds are functions.
codygunton Jan 31, 2024
4ef80d9
Handoff
codygunton Jan 31, 2024
95faf10
used hacky, inefficient method to isolate rounds
lucasxia01 Jan 31, 2024
d3d925d
Isolate target function
codygunton Feb 1, 2024
2dfe774
changed pg and uh round benchmarks to goblin ultra
lucasxia01 Feb 6, 2024
1839ed5
parallelization of compute_full_honk_evaluations leads to:
lucasxia01 Feb 8, 2024
5386e77
Merge remote-tracking branch 'origin/master' into cg-lx/pg-round-benches
lucasxia01 Feb 8, 2024
d8e5319
merge fix
lucasxia01 Feb 8, 2024
99d77b9
Merge remote-tracking branch 'origin/master' into cg-lx/pg-round-benches
codygunton Feb 9, 2024
2fd7a0b
Cleanup
codygunton Feb 9, 2024
73f3830
Goblin benches fixed
codygunton Feb 9, 2024
2badf70
Template benchmarks
codygunton Feb 9, 2024
ef1ffde
Template the other benchmarks
codygunton Feb 9, 2024
57a80a3
Merge remote-tracking branch 'origin/master' into cg-lx/pg-round-benches
codygunton Feb 12, 2024
f1a5549
Little cleanup
codygunton Feb 12, 2024
5b77816
Fix compilation
codygunton Feb 12, 2024
218064c
Fix compilation
codygunton Feb 12, 2024
f65fd51
Fix bug in test function to limit size
codygunton Feb 12, 2024
fbc24ed
Make it pass asserts.
codygunton Feb 12, 2024
eaed02e
Merge remote-tracking branch 'origin/master' into cg-lx/pg-round-benches
codygunton Feb 13, 2024
a76c0c7
Fix sporadic GUH folding failures
codygunton Feb 13, 2024
60d75e5
Remove worktodo
codygunton Feb 13, 2024
8a65de1
Cleanup
codygunton Feb 13, 2024
826aa35
fix: speculative CI fix
ludamad0 Feb 14, 2024
88d48e5
fix: threading
ludamad0 Feb 14, 2024
59ef9cf
Fix ClientIVCTests.Full
codygunton Feb 14, 2024
1ebb590
Revert "fix: speculative CI fix"
codygunton Feb 15, 2024
9e63fcf
round ~> rounds
codygunton Feb 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions barretenberg/cpp/CMakePresets.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,18 @@
"DISABLE_ASM": "ON"
}
},
{
"name": "clang16-dbg-fast",
"displayName": "Optimized debug build with Clang-16",
"description": "Build with globally installed Clang-16 in optimized debug mode",
"inherits": "clang16-dbg",
"environment": {
"CMAKE_BUILD_TYPE": "Debug",
"CFLAGS": "-O2 -gdwarf",
"CXXFLAGS": "-O2 -gdwarf-4",
"LDFLAGS": "-O2 -gdwarf-4"
}
},
{
"name": "asan",
"displayName": "Debugging build with address sanitizer on Clang-16",
Expand Down Expand Up @@ -335,6 +347,11 @@
"inherits": "default",
"configurePreset": "clang16-dbg"
},
{
"name": "clang16-dbg-fast",
"inherits": "default",
"configurePreset": "clang16-dbg-fast"
},
{
"name": "asan",
"inherits": "default",
Expand Down
1 change: 1 addition & 0 deletions barretenberg/cpp/src/barretenberg/benchmark/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ add_subdirectory(ivc_bench)
add_subdirectory(pippenger_bench)
add_subdirectory(plonk_bench)
add_subdirectory(protogalaxy_bench)
add_subdirectory(protogalaxy_rounds_bench)
add_subdirectory(relations_bench)
add_subdirectory(widgets_bench)
add_subdirectory(poseidon2_bench)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,37 +7,44 @@
using namespace benchmark;

namespace bb {
using Flavor = UltraFlavor;
using Instance = ProverInstance_<Flavor>;
using Instances = ProverInstances_<Flavor, 2>;
using ProtoGalaxyProver = ProtoGalaxyProver_<Instances>;
using Builder = Flavor::CircuitBuilder;

// Fold one instance into an accumulator.
void fold_one(State& state) noexcept
template <typename Composer> void fold_one(State& state) noexcept
{
using Flavor = typename Composer::Flavor;
using Instance = ProverInstance_<Flavor>;
using Instances = ProverInstances_<Flavor, 2>;
using ProtoGalaxyProver = ProtoGalaxyProver_<Instances>;
using Builder = typename Flavor::CircuitBuilder;

bb::srs::init_crs_factory("../srs_db/ignition");

auto log2_num_gates = static_cast<size_t>(state.range(0));
auto composer = UltraComposer();
Composer composer;

const auto construct_instance = [&]() {
Builder builder;
bb::mock_proofs::generate_basic_arithmetic_circuit(builder, log2_num_gates);
if constexpr (std::same_as<Flavor, GoblinUltraFlavor>) {
GoblinMockCircuits::construct_arithmetic_circuit(builder, log2_num_gates);
} else {
static_assert(std::same_as<Flavor, UltraFlavor>);
bb::mock_proofs::generate_basic_arithmetic_circuit(builder, log2_num_gates);
}
return composer.create_instance(builder);
};

std::shared_ptr<Instance> instance_1 = construct_instance();
std::shared_ptr<Instance> instance_2 = construct_instance();

auto folding_prover = composer.create_folding_prover({ instance_1, instance_2 });
ProtoGalaxyProver folding_prover = composer.create_folding_prover({ instance_1, instance_2 });

for (auto _ : state) {
auto proof = folding_prover.fold_instances();
}
}

BENCHMARK(fold_one)->/* vary the circuit size */ DenseRange(14, 20)->Unit(kMillisecond);
BENCHMARK(fold_one<UltraComposer>)->/* vary the circuit size */ DenseRange(14, 20)->Unit(kMillisecond);
BENCHMARK(fold_one<GoblinUltraComposer>)->/* vary the circuit size */ DenseRange(14, 20)->Unit(kMillisecond);
} // namespace bb

BENCHMARK_MAIN();
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
barretenberg_module(protogalaxy_rounds_bench ultra_honk protogalaxy stdlib_primitives)
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
barretenberg_module(protogalaxy_round_bench ultra_honk protogalaxy stdlib_primitives)
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#include <benchmark/benchmark.h>

#include "barretenberg/benchmark/ultra_bench/mock_proofs.hpp"
#include "barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp"
#include "barretenberg/ultra_honk/ultra_composer.hpp"

using namespace benchmark;

namespace bb {

template <typename Composer>
void _bench_round(::benchmark::State& state,
void (*F)(ProtoGalaxyProver_<ProverInstances_<typename Composer::Flavor, 2>>&))
{
using Flavor = typename Composer::Flavor;
using Instance = ProverInstance_<Flavor>;
using Builder = typename Flavor::CircuitBuilder;

bb::srs::init_crs_factory("../srs_db/ignition");
auto log2_num_gates = static_cast<size_t>(state.range(0));
auto composer = Composer();

const auto construct_instance = [&]() {
Builder builder;
if constexpr (std::same_as<Flavor, GoblinUltraFlavor>) {
GoblinMockCircuits::construct_arithmetic_circuit(builder, log2_num_gates);
} else {
static_assert(std::same_as<Flavor, UltraFlavor>);
bb::mock_proofs::generate_basic_arithmetic_circuit(builder, log2_num_gates);
}
return composer.create_instance(builder);
};

std::shared_ptr<Instance> instance_1 = construct_instance();
std::shared_ptr<Instance> instance_2 = construct_instance();

auto folding_prover = composer.create_folding_prover({ instance_1, instance_2 });

// prepare the prover state
folding_prover.state.accumulator = instance_1;
folding_prover.state.deltas.resize(log2_num_gates);
std::fill_n(folding_prover.state.deltas.begin(), log2_num_gates, 0);
folding_prover.state.perturbator = Flavor::Polynomial::random(1 << log2_num_gates);
folding_prover.transcript = Flavor::Transcript::prover_init_empty();
folding_prover.preparation_round();

for (auto _ : state) {
F(folding_prover);
}
}

void bench_round_ultra(::benchmark::State& state, void (*F)(ProtoGalaxyProver_<ProverInstances_<UltraFlavor, 2>>&))
{
_bench_round<UltraComposer>(state, F);
}

void bench_round_goblin_ultra(::benchmark::State& state,
void (*F)(ProtoGalaxyProver_<ProverInstances_<GoblinUltraFlavor, 2>>&))
{
_bench_round<GoblinUltraComposer>(state, F);
}

BENCHMARK_CAPTURE(bench_round_ultra, preparation, [](auto& prover) { prover.preparation_round(); })
-> DenseRange(14, 20) -> Unit(kMillisecond);
BENCHMARK_CAPTURE(bench_round_ultra, perturbator, [](auto& prover) { prover.perturbator_round(); })
-> DenseRange(14, 20) -> Unit(kMillisecond);
BENCHMARK_CAPTURE(bench_round_ultra, combiner_quotient, [](auto& prover) { prover.combiner_quotient_round(); })
-> DenseRange(14, 20) -> Unit(kMillisecond);
BENCHMARK_CAPTURE(bench_round_ultra, accumulator_update, [](auto& prover) { prover.accumulator_update_round(); })
-> DenseRange(14, 20) -> Unit(kMillisecond);

BENCHMARK_CAPTURE(bench_round_goblin_ultra, preparation, [](auto& prover) { prover.preparation_round(); })
-> DenseRange(14, 20) -> Unit(kMillisecond);
BENCHMARK_CAPTURE(bench_round_goblin_ultra, perturbator, [](auto& prover) { prover.perturbator_round(); })
-> DenseRange(14, 20) -> Unit(kMillisecond);
BENCHMARK_CAPTURE(bench_round_goblin_ultra, combiner_quotient, [](auto& prover) { prover.combiner_quotient_round(); })
-> DenseRange(14, 20) -> Unit(kMillisecond);
BENCHMARK_CAPTURE(bench_round_goblin_ultra, accumulator_update, [](auto& prover) { prover.accumulator_update_round(); })
-> DenseRange(14, 20) -> Unit(kMillisecond);

} // namespace bb

BENCHMARK_MAIN();
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,16 @@ inline UltraProver get_prover(UltraComposer& composer,
return composer.create_prover(instance);
}

inline GoblinUltraProver get_prover(GoblinUltraComposer& composer,
void (*test_circuit_function)(GoblinUltraComposer::CircuitBuilder&, size_t),
size_t num_iterations)
{
GoblinUltraComposer::CircuitBuilder builder;
test_circuit_function(builder, num_iterations);
std::shared_ptr<GoblinUltraComposer::Instance> instance = composer.create_instance(builder);
return composer.create_prover(instance);
}

// standard plonk
inline plonk::Prover get_prover(plonk::StandardComposer& composer,
void (*test_circuit_function)(StandardCircuitBuilder&, size_t),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ enum {
};

/**
* @details Benchmark ultrahonk by performing all the rounds, but only measuring one.
* @details Benchmark Goblin ultrahonk by performing all the rounds, but only measuring one.
* Note: As a result the very short rounds take a long time for statistical significance, so recommended to set their
* iterations to 1.
* @param state - The google benchmark state.
* @param prover - The ultrahonk prover.
* @param prover - The Goblin ultrahonk prover.
* @param index - The pass to measure.
**/
BB_PROFILE static void test_round_inner(State& state, UltraProver& prover, size_t index) noexcept
BB_PROFILE static void test_round_inner(State& state, GoblinUltraProver& prover, size_t index) noexcept
{
auto time_if_index = [&](size_t target_index, auto&& func) -> void {
BB_REPORT_OP_COUNT_IN_BENCH(state);
Expand All @@ -55,25 +55,23 @@ BB_PROFILE static void test_round_inner(State& state, UltraProver& prover, size_
}
BB_PROFILE static void test_round(State& state, size_t index) noexcept
{
auto log2_num_gates = static_cast<size_t>(state.range(0));
bb::srs::init_crs_factory("../srs_db/ignition");

GoblinUltraComposer composer;
// TODO(https://github.com/AztecProtocol/barretenberg/issues/761) benchmark both sparse and dense circuits
GoblinUltraProver prover = bb::mock_proofs::get_prover(
composer, &bb::mock_proofs::generate_basic_arithmetic_circuit<GoblinUltraCircuitBuilder>, log2_num_gates);
for (auto _ : state) {
state.PauseTiming();
UltraComposer composer;
// TODO(https://github.com/AztecProtocol/barretenberg/issues/761) benchmark both sparse and dense circuits
UltraProver prover = bb::mock_proofs::get_prover(
composer, &bb::stdlib::generate_ecdsa_verification_test_circuit<UltraCircuitBuilder>, 10);
test_round_inner(state, prover, index);
state.ResumeTiming();
// NOTE: google bench is very finnicky, must end in ResumeTiming() for correctness
}
}
#define ROUND_BENCHMARK(round) \
static void ROUND_##round(State& state) noexcept \
{ \
test_round(state, round); \
} \
BENCHMARK(ROUND_##round)->Unit(kMillisecond)
BENCHMARK(ROUND_##round)->DenseRange(17, 19)->Unit(kMillisecond)

// Fast rounds take a long time to benchmark because of how we compute statistical significance.
// Limit to one iteration so we don't spend a lot of time redoing full proofs just to measure this part.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ class ClientIVCTests : public ::testing::Test {
* @details Currently default sized to 2^16 to match kernel. (Note: op gates will bump size to next power of 2)
*
*/
static Builder create_mock_circuit(ClientIVC& ivc, size_t num_gates = 1 << 15)
static Builder create_mock_circuit(ClientIVC& ivc, size_t log2_num_gates = 15)
{
Builder circuit{ ivc.goblin.op_queue };
GoblinMockCircuits::construct_arithmetic_circuit(circuit, num_gates);
GoblinMockCircuits::construct_arithmetic_circuit(circuit, log2_num_gates);
GoblinMockCircuits::construct_goblin_ecc_op_circuit(circuit);
return circuit;
}
Expand Down
15 changes: 15 additions & 0 deletions barretenberg/cpp/src/barretenberg/flavor/goblin_ultra.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,21 @@ class GoblinUltraFlavor {
: NativeTranscript(proof)
{}

static std::shared_ptr<Transcript_> prover_init_empty()
{
auto transcript = std::make_shared<Transcript_>();
constexpr uint32_t init{ 42 }; // arbitrary
transcript->send_to_verifier("Init", init);
return transcript;
};

static std::shared_ptr<Transcript_> verifier_init_empty(const std::shared_ptr<Transcript_>& transcript)
{
auto verifier_transcript = std::make_shared<Transcript_>(transcript->proof_data);
[[maybe_unused]] auto _ = verifier_transcript->template receive_from_prover<uint32_t>("Init");
return verifier_transcript;
};

void deserialize_full_transcript()
{
// take current proof and put them into the struct
Expand Down
22 changes: 12 additions & 10 deletions barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ class GoblinMockCircuits {
* @param builder
* @param num_gates
*/
static void construct_arithmetic_circuit(GoblinUltraBuilder& builder, size_t num_gates = 1)
static void construct_arithmetic_circuit(GoblinUltraBuilder& builder, size_t log2_num_gates = 0)
{
size_t num_gates = 1 << log2_num_gates;
// For good measure, include a gate with some public inputs
{
FF a = FF::random_element();
Expand All @@ -53,17 +54,18 @@ class GoblinMockCircuits {

builder.create_big_add_gate({ a_idx, b_idx, c_idx, d_idx, FF(1), FF(1), FF(1), FF(-1), FF(0) });
}

// Add arbitrary arithmetic gates to obtain a total of num_gates-many gates
for (size_t i = 0; i < num_gates - 1; ++i) {
FF a = FF::random_element();
FF b = FF::random_element();
FF c = FF::random_element();
FF d = a + b + c;
uint32_t a_idx = builder.add_variable(a);
uint32_t b_idx = builder.add_variable(b);
uint32_t c_idx = builder.add_variable(c);
uint32_t d_idx = builder.add_variable(d);
FF a = FF::random_element();
FF b = FF::random_element();
FF c = FF::random_element();
FF d = a + b + c;
uint32_t a_idx = builder.add_variable(a);
uint32_t b_idx = builder.add_variable(b);
uint32_t c_idx = builder.add_variable(c);
uint32_t d_idx = builder.add_variable(d);

for (size_t i = 0; i < num_gates - 1; ++i) {
builder.create_big_add_gate({ a_idx, b_idx, c_idx, d_idx, FF(1), FF(1), FF(1), FF(-1), FF(0) });
}
}
Expand Down
Loading
Loading