Skip to content

Commit

Permalink
feat: Clarify state in Protogalaxy 3 (#8181)
Browse files Browse the repository at this point in the history
Main goal: more explicit state by making round functions pure functions
(with const inputs).
- Exception: first round mutates instances. May handle in follow-on that
changes handling of accumulator.
- Also: get rid of several pieces of prover state (`gate_challenges`,
`relation_parameters`, `optimised_relation_parameters`, `accumulators`,
`result`)
- FYI: will likely get rid of temporary refactoring helper classes
`State` and `ProtogalaxyProverInternal` also.

Also:
- Rename `accumulator_update_round`, `preparation_round`,
`compressed_perturbator`, `OptimisedFoo`, `CombinedFoo`.
 - Combiner test does not use prover class.
 - Use `const` in a bunch of places
- Reduce amount of templating by explicitly naming instantiations of
compute_combiner
  • Loading branch information
codygunton authored Aug 30, 2024
1 parent 4e2ce80 commit 4a9bb9d
Show file tree
Hide file tree
Showing 12 changed files with 289 additions and 294 deletions.
6 changes: 3 additions & 3 deletions barretenberg/cpp/scripts/analyze_client_ivc_bench.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
"ProtoGalaxyProver_::preparation_round(t)",
"ProtoGalaxyProver_::perturbator_round(t)",
"ProtoGalaxyProver_::combiner_quotient_round(t)",
"ProtoGalaxyProver_::accumulator_update_round(t)"
"ProtoGalaxyProver_::update_target_sum_and_fold(t)"
]
max_label_length = max(len(label) for label in protogalaxy_round_labels)
for key in protogalaxy_round_labels:
Expand All @@ -80,7 +80,7 @@
total_time_ms = bench["ProtogalaxyProver::prove(t)"]/1e6
print(f"{key:<{max_label_length}}{time_ms:>8.0f} {time_ms/total_time_ms:>8.2%}")

# Extract a set of components from the benchmark data and display timings and relative percentages
# Extract a set of components from the benchmark data and display timings and relative percentages
def print_contributions(prefix, ivc_bench_json, bench_name, components):

# Read JSON file and extract benchmark
Expand All @@ -93,7 +93,7 @@ def print_contributions(prefix, ivc_bench_json, bench_name, components):
except FileNotFoundError:
print(f"File not found: {prefix / ivc_bench_json}")
return

# Filter and sum up kept times
bench_components = {key: bench[key] for key in components if key in bench}
sum_of_kept_times_ms = sum(float(time) for time in bench_components.values()) / 1e6
Expand Down
8 changes: 4 additions & 4 deletions barretenberg/cpp/scripts/analyze_protogalaxy_bench.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@

print('\nBreakdown of ProtogalaxyProver::prove:')
protogalaxy_round_labels = [
"ProtoGalaxyProver_::preparation_round(t)",
"ProtoGalaxyProver_::perturbator_round(t)",
"ProtoGalaxyProver_::combiner_quotient_round(t)",
"ProtoGalaxyProver_::accumulator_update_round(t)"
"ProtoGalaxyProver_::preparation_round(t)",
"ProtoGalaxyProver_::perturbator_round(t)",
"ProtoGalaxyProver_::combiner_quotient_round(t)",
"ProtoGalaxyProver_::update_target_sum_and_fold(t)"
]
max_label_length = max(len(label) for label in protogalaxy_round_labels)
for key in protogalaxy_round_labels:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ void _bench_round(::benchmark::State& state, void (*F)(ProtoGalaxyProver_<Prover
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();
folding_prover.run_oink_prover_on_each_instance();

for (auto _ : state) {
F(folding_prover);
Expand All @@ -51,14 +51,21 @@ void bench_round_mega(::benchmark::State& state, void (*F)(ProtoGalaxyProver_<Pr
_bench_round<MegaFlavor>(state, F);
}

BENCHMARK_CAPTURE(bench_round_mega, preparation, [](auto& prover) { prover.preparation_round(); }) -> DenseRange(14, 20)
-> Unit(kMillisecond);
BENCHMARK_CAPTURE(bench_round_mega, perturbator, [](auto& prover) { prover.perturbator_round(); }) -> DenseRange(14, 20)
-> Unit(kMillisecond);
BENCHMARK_CAPTURE(bench_round_mega, combiner_quotient, [](auto& prover) { prover.combiner_quotient_round(); })
-> DenseRange(14, 20) -> Unit(kMillisecond);
BENCHMARK_CAPTURE(bench_round_mega, accumulator_update, [](auto& prover) { prover.accumulator_update_round(); })
BENCHMARK_CAPTURE(bench_round_mega, oink, [](auto& prover) { prover.run_oink_prover_on_each_instance(); })
-> DenseRange(14, 20) -> Unit(kMillisecond);
BENCHMARK_CAPTURE(bench_round_mega, perturbator, [](auto& prover) {
prover.perturbator_round(prover.state.accumulator);
}) -> DenseRange(14, 20) -> Unit(kMillisecond);
BENCHMARK_CAPTURE(bench_round_mega, combiner_quotient, [](auto& prover) {
prover.combiner_quotient_round(prover.state.accumulator->gate_challenges, prover.state.deltas, prover.instances);
}) -> DenseRange(14, 20) -> Unit(kMillisecond);
BENCHMARK_CAPTURE(bench_round_mega, fold, [](auto& prover) {
prover.update_target_sum_and_fold(prover.instances,
prover.state.combiner_quotient,
prover.state.alphas,
prover.state.relation_parameters,
prover.state.perturbator_evaluation);
}) -> DenseRange(14, 20) -> Unit(kMillisecond);

} // namespace bb

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,7 @@ template <class Fr, size_t domain_end, size_t domain_start = 0, size_t skip_coun
* @param f
* @return Fr
*/
Fr evaluate(const Fr& u)
Fr evaluate(const Fr& u) const
{
using Data = BarycentricData<Fr, domain_end, LENGTH, domain_start>;
Fr full_numerator_value = 1;
Expand Down
76 changes: 29 additions & 47 deletions barretenberg/cpp/src/barretenberg/protogalaxy/combiner.test.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#include "barretenberg/honk/utils/testing.hpp"
#include "barretenberg/protogalaxy/protogalaxy_prover.hpp"
#include "barretenberg/protogalaxy/protogalaxy_prover_internal.hpp"
#include "barretenberg/relations/ultra_arithmetic_relation.hpp"
#include "barretenberg/stdlib_circuit_builders/ultra_flavor.hpp"
Expand All @@ -19,7 +18,6 @@ TEST(Protogalaxy, CombinerOn2Instances)
constexpr size_t NUM_INSTANCES = 2;
using ProverInstance = ProverInstance_<Flavor>;
using ProverInstances = ProverInstances_<Flavor, NUM_INSTANCES>;
using ProtoGalaxyProver = ProtoGalaxyProver_<ProverInstances>;
using Fun = ProtogalaxyProverInternal<ProverInstances>;

const auto restrict_to_standard_arithmetic_relation = [](auto& polys) {
Expand All @@ -40,7 +38,6 @@ TEST(Protogalaxy, CombinerOn2Instances)
// relation.
if (is_random_input) {
std::vector<std::shared_ptr<ProverInstance>> instance_data(NUM_INSTANCES);
ProtoGalaxyProver prover;

for (size_t idx = 0; idx < NUM_INSTANCES; idx++) {
auto instance = std::make_shared<ProverInstance>();
Expand All @@ -54,13 +51,12 @@ TEST(Protogalaxy, CombinerOn2Instances)
}

ProverInstances instances{ instance_data };
prover.state.alphas.fill(bb::Univariate<FF, 12>(FF(0))); // focus on the arithmetic relation only
Fun::UnivariateRelationSeparator alphas;
alphas.fill(bb::Univariate<FF, 12>(FF(0))); // focus on the arithmetic relation only
PowPolynomial<FF> pow_polynomial({ 2 }, /*log_num_monomials=*/1);
auto result = Fun::compute_combiner(instances,
pow_polynomial,
prover.state.relation_parameters,
prover.state.alphas,
prover.state.univariate_accumulators);
Fun::UnivariateRelationParametersNoOptimisticSkipping univariate_relation_parameters;
auto result = Fun::compute_combiner_no_optimistic_skipping(
instances, pow_polynomial, univariate_relation_parameters, alphas);
// The expected_result values are computed by running the python script combiner_example_gen.py
auto expected_result = Univariate<FF, 12>(std::array<FF, 12>{ 9704UL,
13245288UL,
Expand All @@ -77,7 +73,6 @@ TEST(Protogalaxy, CombinerOn2Instances)
EXPECT_EQ(result, expected_result);
} else {
std::vector<std::shared_ptr<ProverInstance>> instance_data(NUM_INSTANCES);
ProtoGalaxyProver prover;

for (size_t idx = 0; idx < NUM_INSTANCES; idx++) {
auto instance = std::make_shared<ProverInstance>();
Expand All @@ -91,7 +86,8 @@ TEST(Protogalaxy, CombinerOn2Instances)
}

ProverInstances instances{ instance_data };
prover.state.alphas.fill(bb::Univariate<FF, 12>(FF(0))); // focus on the arithmetic relation only
Fun::UnivariateRelationSeparator alphas;
alphas.fill(bb::Univariate<FF, 12>(FF(0))); // focus on the arithmetic relation only

const auto create_add_gate = [](auto& polys, const size_t idx, FF w_l, FF w_r) {
polys.w_l[idx] = w_l;
Expand Down Expand Up @@ -138,16 +134,12 @@ TEST(Protogalaxy, CombinerOn2Instances)
0 0 0 0 0 0 0 0 0 6 18 36 60 90 */

PowPolynomial<FF> pow_polynomial({ 2 }, /*log_num_monomials=*/1);
auto result = Fun::compute_combiner(instances,
pow_polynomial,
prover.state.relation_parameters,
prover.state.alphas,
prover.state.univariate_accumulators);
auto optimised_result = Fun::compute_combiner(instances,
pow_polynomial,
prover.state.optimised_relation_parameters,
prover.state.alphas,
prover.state.optimised_univariate_accumulators);
Fun::UnivariateRelationParametersNoOptimisticSkipping univariate_relation_parameters;
Fun::UnivariateRelationParameters optimised_univariate_relation_parameters;
auto result = Fun::compute_combiner_no_optimistic_skipping(
instances, pow_polynomial, univariate_relation_parameters, alphas);
auto optimised_result =
Fun::compute_combiner(instances, pow_polynomial, optimised_univariate_relation_parameters, alphas);
auto expected_result =
Univariate<FF, 12>(std::array<FF, 12>{ 0, 0, 12, 36, 72, 120, 180, 252, 336, 432, 540, 660 });

Expand All @@ -165,7 +157,6 @@ TEST(Protogalaxy, CombinerOptimizationConsistency)
constexpr size_t NUM_INSTANCES = 2;
using ProverInstance = ProverInstance_<Flavor>;
using ProverInstances = ProverInstances_<Flavor, NUM_INSTANCES>;
using ProtoGalaxyProver = ProtoGalaxyProver_<ProverInstances>;
using Fun = ProtogalaxyProverInternal<ProverInstances>;
using UltraArithmeticRelation = UltraArithmeticRelation<FF>;

Expand All @@ -187,7 +178,6 @@ TEST(Protogalaxy, CombinerOptimizationConsistency)
if (is_random_input) {
std::vector<std::shared_ptr<ProverInstance>> instance_data(NUM_INSTANCES);
ASSERT(NUM_INSTANCES == 2); // Don't want to handle more here
ProtoGalaxyProver prover;

for (size_t idx = 0; idx < NUM_INSTANCES; idx++) {
auto instance = std::make_shared<ProverInstance>();
Expand All @@ -201,8 +191,8 @@ TEST(Protogalaxy, CombinerOptimizationConsistency)
}

ProverInstances instances{ instance_data };
prover.state.alphas.fill(
bb::Univariate<FF, UNIVARIATE_LENGTH>(FF(0))); // focus on the arithmetic relation only
Fun::UnivariateRelationSeparator alphas;
alphas.fill(bb::Univariate<FF, UNIVARIATE_LENGTH>(FF(0))); // focus on the arithmetic relation only
PowPolynomial<FF> pow_polynomial({ 2 }, /*log_num_monomials=*/1);

// Relation parameters are all zeroes
Expand Down Expand Up @@ -264,22 +254,17 @@ TEST(Protogalaxy, CombinerOptimizationConsistency)
precomputed_result[idx] = std::get<0>(accumulator)[0];
}
auto expected_result = Univariate<FF, UNIVARIATE_LENGTH>(precomputed_result);
auto result = Fun::compute_combiner(instances,
pow_polynomial,
prover.state.relation_parameters,
prover.state.alphas,
prover.state.univariate_accumulators);
auto optimised_result = Fun::compute_combiner(instances,
pow_polynomial,
prover.state.optimised_relation_parameters,
prover.state.alphas,
prover.state.optimised_univariate_accumulators);
Fun::UnivariateRelationParametersNoOptimisticSkipping univariate_relation_parameters;
Fun::UnivariateRelationParameters optimised_univariate_relation_parameters;
auto result = Fun::compute_combiner_no_optimistic_skipping(
instances, pow_polynomial, univariate_relation_parameters, alphas);
auto optimised_result =
Fun::compute_combiner(instances, pow_polynomial, optimised_univariate_relation_parameters, alphas);

EXPECT_EQ(result, expected_result);
EXPECT_EQ(optimised_result, expected_result);
} else {
std::vector<std::shared_ptr<ProverInstance>> instance_data(NUM_INSTANCES);
ProtoGalaxyProver prover;

for (size_t idx = 0; idx < NUM_INSTANCES; idx++) {
auto instance = std::make_shared<ProverInstance>();
Expand All @@ -293,7 +278,8 @@ TEST(Protogalaxy, CombinerOptimizationConsistency)
}

ProverInstances instances{ instance_data };
prover.state.alphas.fill(bb::Univariate<FF, 12>(FF(0))); // focus on the arithmetic relation only
Fun::UnivariateRelationSeparator alphas;
alphas.fill(bb::Univariate<FF, 12>(FF(0))); // focus on the arithmetic relation only

const auto create_add_gate = [](auto& polys, const size_t idx, FF w_l, FF w_r) {
polys.w_l[idx] = w_l;
Expand Down Expand Up @@ -340,16 +326,12 @@ TEST(Protogalaxy, CombinerOptimizationConsistency)
0 0 0 0 0 0 0 0 0 6 18 36 60 90 */

PowPolynomial<FF> pow_polynomial({ 2 }, /*log_num_monomials=*/1);
auto result = Fun::compute_combiner(instances,
pow_polynomial,
prover.state.relation_parameters,
prover.state.alphas,
prover.state.univariate_accumulators);
auto optimised_result = Fun::compute_combiner(instances,
pow_polynomial,
prover.state.optimised_relation_parameters,
prover.state.alphas,
prover.state.optimised_univariate_accumulators);
Fun::UnivariateRelationParametersNoOptimisticSkipping univariate_relation_parameters;
Fun::UnivariateRelationParameters optimised_univariate_relation_parameters;
auto result = Fun::compute_combiner_no_optimistic_skipping(
instances, pow_polynomial, univariate_relation_parameters, alphas);
auto optimised_result =
Fun::compute_combiner(instances, pow_polynomial, optimised_univariate_relation_parameters, alphas);
auto expected_result =
Univariate<FF, 12>(std::array<FF, 12>{ 0, 0, 12, 36, 72, 120, 180, 252, 336, 432, 540, 660 });

Expand Down
34 changes: 17 additions & 17 deletions barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -232,23 +232,23 @@ template <typename Flavor> class ProtoGalaxyTests : public testing::Test {
*/
static void test_combiner_quotient()
{
auto compressed_perturbator = FF(2); // F(\alpha) in the paper
auto perturbator_evaluation = FF(2); // F(\alpha) in the paper
auto combiner = bb::Univariate<FF, 12>(std::array<FF, 12>{ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 });
auto combiner_quotient = Fun::compute_combiner_quotient(compressed_perturbator, combiner);
auto combiner_quotient = Fun::compute_combiner_quotient(perturbator_evaluation, combiner);

// K(i) = (G(i) - ( L_0(i) * F(\alpha)) / Z(i), i = {2,.., 13} for ProverInstances::NUM = 2
// K(i) = (G(i) - (1 - i) * F(\alpha)) / i * (i - 1)
auto expected_evals = bb::Univariate<FF, 12, 2>(std::array<FF, 10>{
(FF(22) - (FF(1) - FF(2)) * compressed_perturbator) / (FF(2) * FF(2 - 1)),
(FF(23) - (FF(1) - FF(3)) * compressed_perturbator) / (FF(3) * FF(3 - 1)),
(FF(24) - (FF(1) - FF(4)) * compressed_perturbator) / (FF(4) * FF(4 - 1)),
(FF(25) - (FF(1) - FF(5)) * compressed_perturbator) / (FF(5) * FF(5 - 1)),
(FF(26) - (FF(1) - FF(6)) * compressed_perturbator) / (FF(6) * FF(6 - 1)),
(FF(27) - (FF(1) - FF(7)) * compressed_perturbator) / (FF(7) * FF(7 - 1)),
(FF(28) - (FF(1) - FF(8)) * compressed_perturbator) / (FF(8) * FF(8 - 1)),
(FF(29) - (FF(1) - FF(9)) * compressed_perturbator) / (FF(9) * FF(9 - 1)),
(FF(30) - (FF(1) - FF(10)) * compressed_perturbator) / (FF(10) * FF(10 - 1)),
(FF(31) - (FF(1) - FF(11)) * compressed_perturbator) / (FF(11) * FF(11 - 1)),
(FF(22) - (FF(1) - FF(2)) * perturbator_evaluation) / (FF(2) * FF(2 - 1)),
(FF(23) - (FF(1) - FF(3)) * perturbator_evaluation) / (FF(3) * FF(3 - 1)),
(FF(24) - (FF(1) - FF(4)) * perturbator_evaluation) / (FF(4) * FF(4 - 1)),
(FF(25) - (FF(1) - FF(5)) * perturbator_evaluation) / (FF(5) * FF(5 - 1)),
(FF(26) - (FF(1) - FF(6)) * perturbator_evaluation) / (FF(6) * FF(6 - 1)),
(FF(27) - (FF(1) - FF(7)) * perturbator_evaluation) / (FF(7) * FF(7 - 1)),
(FF(28) - (FF(1) - FF(8)) * perturbator_evaluation) / (FF(8) * FF(8 - 1)),
(FF(29) - (FF(1) - FF(9)) * perturbator_evaluation) / (FF(9) * FF(9 - 1)),
(FF(30) - (FF(1) - FF(10)) * perturbator_evaluation) / (FF(10) * FF(10 - 1)),
(FF(31) - (FF(1) - FF(11)) * perturbator_evaluation) / (FF(11) * FF(11 - 1)),
});

for (size_t idx = 2; idx < 7; idx++) {
Expand All @@ -273,18 +273,18 @@ template <typename Flavor> class ProtoGalaxyTests : public testing::Test {
instance2->relation_parameters.eta = 3;

ProverInstances instances{ { instance1, instance2 } };
auto relation_parameters_no_optimistic_skipping = Fun::template compute_extended_relation_parameters<
typename Fun::UnivariateRelationParametersNoOptimisticSkipping>(instances);
auto relation_parameters =
Fun::template compute_extended_relation_parameters<typename FoldingProver::State::RelationParameters>(
Fun::template compute_extended_relation_parameters<typename FoldingProver::UnivariateRelationParameters>(
instances);
auto optimised_relation_parameters = Fun::template compute_extended_relation_parameters<
typename FoldingProver::State::OptimisedRelationParameters>(instances);

bb::Univariate<FF, 11> expected_eta{ { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21 } };
EXPECT_EQ(relation_parameters.eta, expected_eta);
EXPECT_EQ(relation_parameters_no_optimistic_skipping.eta, expected_eta);
// Optimised relation parameters are the same, we just don't compute any values for non-used indices when
// deriving values from them
for (size_t i = 0; i < 11; i++) {
EXPECT_EQ(optimised_relation_parameters.eta.evaluations[i], expected_eta.evaluations[i]);
EXPECT_EQ(relation_parameters.eta.evaluations[i], expected_eta.evaluations[i]);
}
}

Expand Down
Loading

0 comments on commit 4a9bb9d

Please sign in to comment.