Skip to content

Commit

Permalink
feat: Avoiding redundant computation in PG (#5844)
Browse files Browse the repository at this point in the history
This PR reduces PG computation time by removing computation on indices
over which accumulated relation values are expected to be zero. This
gives us a speedup of 4-5%. The PR also parallelised pertubator root
construction.
Before:
x86_64:

![image](https://github.com/AztecProtocol/aztec-packages/assets/4798775/80247864-1c1c-4e34-8756-a8bd44bdbab2)
wasm:

![image](https://github.com/AztecProtocol/aztec-packages/assets/4798775/649dfd97-d65c-48a5-8b8c-02fb3fbb9f47)
After:
x86_64:

![image](https://github.com/AztecProtocol/aztec-packages/assets/4798775/d453e026-7a88-4646-8094-b7102916a2af)
wasm:

![image](https://github.com/AztecProtocol/aztec-packages/assets/4798775/549b89a3-d1dd-4058-84a2-92856180d15d)
  • Loading branch information
Rumata888 authored Apr 30, 2024
1 parent 1904fa8 commit 9f57733
Show file tree
Hide file tree
Showing 11 changed files with 445 additions and 144 deletions.
15 changes: 10 additions & 5 deletions barretenberg/cpp/src/barretenberg/flavor/flavor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -251,18 +251,23 @@ template <typename Tuple, std::size_t Index = 0> static constexpr size_t compute
* @details The size of the outer tuple is equal to the number of relations. Each relation contributes an inner tuple of
* univariates whose size is equal to the number of subrelations of the relation. The length of a univariate in an inner
* tuple is determined by the corresponding subrelation length and the number of instances to be folded.
* @tparam optimised Enable optimised version with skipping some of the computation
*/
template <typename Tuple, size_t NUM_INSTANCES, size_t Index = 0>
template <typename Tuple, size_t NUM_INSTANCES, bool optimised = false, size_t Index = 0>
static constexpr auto create_protogalaxy_tuple_of_tuples_of_univariates()
{
if constexpr (Index >= std::tuple_size<Tuple>::value) {
return std::tuple<>{}; // Return empty when reach end of the tuple
} else {
using UnivariateTuple =
typename std::tuple_element_t<Index,
Tuple>::template ProtogalaxyTupleOfUnivariatesOverSubrelations<NUM_INSTANCES>;
return std::tuple_cat(std::tuple<UnivariateTuple>{},
create_protogalaxy_tuple_of_tuples_of_univariates<Tuple, NUM_INSTANCES, Index + 1>());
std::conditional_t<optimised,
typename std::tuple_element_t<Index, Tuple>::
template OptimisedProtogalaxyTupleOfUnivariatesOverSubrelations<NUM_INSTANCES>,
typename std::tuple_element_t<Index, Tuple>::
template ProtogalaxyTupleOfUnivariatesOverSubrelations<NUM_INSTANCES>>;
return std::tuple_cat(
std::tuple<UnivariateTuple>{},
create_protogalaxy_tuple_of_tuples_of_univariates<Tuple, NUM_INSTANCES, optimised, Index + 1>());
}
}

Expand Down
214 changes: 137 additions & 77 deletions barretenberg/cpp/src/barretenberg/polynomials/univariate.hpp

Large diffs are not rendered by default.

44 changes: 27 additions & 17 deletions barretenberg/cpp/src/barretenberg/protogalaxy/combiner.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ TEST(Protogalaxy, CombinerOn2Instances)
auto prover_polynomials = get_sequential_prover_polynomials<Flavor>(
/*log_circuit_size=*/1, idx * 128);
restrict_to_standard_arithmetic_relation(prover_polynomials);
// This ensures that the combiner accumulator for second instance = 0
// The value is computed by generating the python script values, computing the resulting accumulator and
// taking the value at index 1
if (idx == NUM_INSTANCES - 1) {
prover_polynomials.q_c[0] -= 13644570;
}
instance->proving_key.polynomials = std::move(prover_polynomials);
instance->proving_key.circuit_size = 2;
instance_data[idx] = instance;
Expand All @@ -52,22 +58,22 @@ TEST(Protogalaxy, CombinerOn2Instances)
ProverInstances instances{ instance_data };
instances.alphas.fill(bb::Univariate<FF, 12>(FF(0))); // focus on the arithmetic relation only
auto pow_polynomial = PowPolynomial(std::vector<FF>{ 2 });
auto result = prover.compute_combiner(instances, pow_polynomial);
auto expected_result = Univariate<FF, 12>(std::array<FF, 12>{
87706,
13644570,
76451738,
226257946,
static_cast<uint64_t>(500811930),
static_cast<uint64_t>(937862426),
static_cast<uint64_t>(1575158170),
static_cast<uint64_t>(2450447898),
static_cast<uint64_t>(3601480346),
static_cast<uint64_t>(5066004250),
static_cast<uint64_t>(6881768346),
static_cast<uint64_t>(9086521370),
});
auto result = prover.compute_combiner</*OptimisationEnabled=*/false>(instances, pow_polynomial);
auto optimised_result = prover.compute_combiner(instances, pow_polynomial);
auto expected_result = Univariate<FF, 12>(std::array<FF, 12>{ 87706,
0,
0x02ee2966,
0x0b0bd2cc,
0x00001a98fc32,
0x000033d5a598,
0x00005901cefe,
0x00008c5d7864,
0x0000d028a1ca,
0x000126a34b30UL,
0x0001920d7496UL,
0x000214a71dfcUL });
EXPECT_EQ(result, expected_result);
EXPECT_EQ(optimised_result, expected_result);
} else {
std::vector<std::shared_ptr<ProverInstance>> instance_data(NUM_INSTANCES);
ProtoGalaxyProver prover;
Expand Down Expand Up @@ -130,11 +136,13 @@ TEST(Protogalaxy, CombinerOn2Instances)
0 0 0 0 0 0 0 0 0 6 18 36 60 90 */

auto pow_polynomial = PowPolynomial(std::vector<FF>{ 2 });
auto result = prover.compute_combiner(instances, pow_polynomial);
auto result = prover.compute_combiner</*OptimisationEnabled=*/false>(instances, pow_polynomial);
auto optimised_result = prover.compute_combiner(instances, pow_polynomial);
auto expected_result =
Univariate<FF, 12>(std::array<FF, 12>{ 0, 0, 12, 36, 72, 120, 180, 252, 336, 432, 540, 660 });

EXPECT_EQ(result, expected_result);
EXPECT_EQ(optimised_result, expected_result);
}
};
run_test(true);
Expand Down Expand Up @@ -181,11 +189,13 @@ TEST(Protogalaxy, CombinerOn4Instances)
zero_all_selectors(instances[3]->proving_key.polynomials);

auto pow_polynomial = PowPolynomial(std::vector<FF>{ 2 });
auto result = prover.compute_combiner(instances, pow_polynomial);
auto result = prover.compute_combiner</*OptimisationEnabled=*/false>(instances, pow_polynomial);
auto optimised_result = prover.compute_combiner(instances, pow_polynomial);
std::array<FF, 40> zeroes;
std::fill(zeroes.begin(), zeroes.end(), 0);
auto expected_result = Univariate<FF, 40>(zeroes);
EXPECT_EQ(result, expected_result);
EXPECT_EQ(optimised_result, expected_result);
};
run_test();
};
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,11 @@ template <typename Flavor> class ProtoGalaxyTests : public testing::Test {

bb::Univariate<FF, 11> expected_eta{ { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21 } };
EXPECT_EQ(instances.relation_parameters.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(instances.optimised_relation_parameters.eta.evaluations[i], expected_eta.evaluations[i]);
}
}

/**
Expand Down
Loading

0 comments on commit 9f57733

Please sign in to comment.