Skip to content

Commit

Permalink
feat: Parallelize linearly dependent contribution in PG (#4742)
Browse files Browse the repository at this point in the history
Closes  AztecProtocol/barretenberg#856.

Changes accumulating the linearly dependent contribution to be
non-serial in protogalaxy, by incorporating its accumulation in the
parallel loop
  • Loading branch information
Rumata888 committed Mar 13, 2024
1 parent 7af68ef commit d1799ae
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ template <typename Flavor> class ProtoGalaxyTests : public testing::Test {
static void construct_circuit(Builder& builder)
{
if constexpr (IsGoblinFlavor<Flavor>) {
GoblinMockCircuits::construct_arithmetic_circuit(builder);
GoblinMockCircuits::construct_arithmetic_circuit(builder, 200);
GoblinMockCircuits::construct_goblin_ecc_op_circuit(builder);

} else {
Expand Down Expand Up @@ -109,8 +109,8 @@ template <typename Flavor> class ProtoGalaxyTests : public testing::Test {

/**
* @brief For a valid circuit, ensures that computing the value of the full UH/UGH relation at each row in its
* execution trace (with the contribution of the linearly dependent one added tot he first row, in case of Goblin)
* will be 0.
* execution trace (with the contribution of the linearly dependent one added tot he first row, in case of
* Goblin) will be 0.
*
*/
static void test_full_honk_evaluations_valid_circuit()
Expand Down Expand Up @@ -143,8 +143,8 @@ template <typename Flavor> class ProtoGalaxyTests : public testing::Test {
}

/**
* @brief Check the coefficients of the perturbator computed from dummy \vec{β}, \vec{δ} and f_i(ω) will be the same
* as if computed manually.
* @brief Check the coefficients of the perturbator computed from dummy \vec{β}, \vec{δ} and f_i(ω) will be the
* same as if computed manually.
*
*/
static void test_pertubator_coefficients()
Expand Down Expand Up @@ -213,8 +213,8 @@ template <typename Flavor> class ProtoGalaxyTests : public testing::Test {
}

/**
* @brief Manually compute the expected evaluations of the combiner quotient, given evaluations of the combiner and
* check them against the evaluations returned by the function.
* @brief Manually compute the expected evaluations of the combiner quotient, given evaluations of the combiner
* and check them against the evaluations returned by the function.
*
*/
static void test_combiner_quotient()
Expand Down Expand Up @@ -246,8 +246,8 @@ template <typename Flavor> class ProtoGalaxyTests : public testing::Test {
}

/**
* @brief For two dummy instances with their relation parameter η set, check that combining them in a univariate,
* barycentrially extended to the desired number of evaluations, is performed correctly.
* @brief For two dummy instances with their relation parameter η set, check that combining them in a
* univariate, barycentrially extended to the desired number of evaluations, is performed correctly.
*
*/
static void test_combine_relation_parameters()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,31 +149,43 @@ template <class ProverInstances_> class ProtoGalaxyProver_ {
auto instance_size = instance_polynomials.get_polynomial_size();
std::vector<FF> full_honk_evaluations(instance_size);
std::vector<FF> linearly_dependent_contributions(instance_size);
parallel_for(instance_size, [&](size_t row) {
auto row_evaluations = instance_polynomials.get_row(row);
RelationEvaluations relation_evaluations;
Utils::zero_elements(relation_evaluations);

// Note that the evaluations are accumulated with the gate separation challenge
// being 1 at this stage, as this specific randomness is added later through the
// power polynomial univariate specific to ProtoGalaxy
Utils::template accumulate_relation_evaluations<>(
row_evaluations, relation_evaluations, relation_parameters, FF(1));

auto output = FF(0);
auto running_challenge = FF(1);

// Sum relation evaluations, batched by their corresponding relation separator challenge, to
// get the value of the full honk relation at a specific row
linearly_dependent_contributions[row] = 0;
Utils::scale_and_batch_elements(
relation_evaluations, alpha, running_challenge, output, linearly_dependent_contributions[row]);
full_honk_evaluations[row] = output;
#ifndef NO_MULTITHREADING
std::mutex evaluation_mutex;
#endif
auto linearly_dependent_contribution_accumulator = FF(0);
run_loop_in_parallel(instance_size, [&](size_t start_row, size_t end_row) {
auto thread_accumulator = FF(0);
for (size_t row = start_row; row < end_row; row++) {
auto row_evaluations = instance_polynomials.get_row(row);
RelationEvaluations relation_evaluations;
Utils::zero_elements(relation_evaluations);

// Note that the evaluations are accumulated with the gate separation challenge
// being 1 at this stage, as this specific randomness is added later through the
// power polynomial univariate specific to ProtoGalaxy
Utils::template accumulate_relation_evaluations<>(
row_evaluations, relation_evaluations, relation_parameters, FF(1));

auto output = FF(0);
auto running_challenge = FF(1);

// Sum relation evaluations, batched by their corresponding relation separator challenge, to
// get the value of the full honk relation at a specific row
auto linearly_dependent_contribution = FF(0);
Utils::scale_and_batch_elements(
relation_evaluations, alpha, running_challenge, output, linearly_dependent_contribution);
thread_accumulator += linearly_dependent_contribution;

full_honk_evaluations[row] = output;
}
{
#ifndef NO_MULTITHREADING
std::unique_lock<std::mutex> evaluation_lock(evaluation_mutex);
#endif
linearly_dependent_contribution_accumulator += thread_accumulator;
}
});

for (FF& linearly_dependent_contribution : linearly_dependent_contributions) {
full_honk_evaluations[0] += linearly_dependent_contribution;
}
full_honk_evaluations[0] += linearly_dependent_contribution_accumulator;
return full_honk_evaluations;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -232,8 +232,8 @@ template <typename RecursiveFlavor> class ProtoGalaxyRecursiveTests : public tes
* make sure the verifer circuits pass check_circuit(). Ensure that the algorithm of the recursive and native
* verifiers are identical by checking the manifests
*/
// TODO(https://github.com/AztecProtocol/barretenberg/issues/844): Fold the recursive folding verifier in tests once
// we can fold instances of different sizes.
// TODO(https://github.com/AztecProtocol/barretenberg/issues/844): Fold the recursive folding verifier in
// tests once we can fold instances of different sizes.
static void test_full_protogalaxy_recursive()
{
// Create two arbitrary circuits for the first round of folding
Expand Down Expand Up @@ -298,15 +298,6 @@ template <typename RecursiveFlavor> class ProtoGalaxyRecursiveTests : public tes
pairing_points[0].get_value(), pairing_points[1].get_value());
EXPECT_EQ(native_result, recursive_result);

// Ensure that the underlying native and recursive decider verification algorithms agree by ensuring
// the manifests produced are the same.
auto recursive_decider_manifest = decider_verifier.transcript->get_manifest();
auto native_decider_manifest = native_decider_verifier.transcript->get_manifest();
for (size_t i = 0; i < recursive_decider_manifest.size(); ++i) {
EXPECT_EQ(recursive_decider_manifest[i], native_decider_manifest[i]);
}

// Construct and verify a proof of the recursive decider verifier circuit
{
auto instance = std::make_shared<ProverInstance>(decider_circuit);
Prover prover(instance);
Expand Down

0 comments on commit d1799ae

Please sign in to comment.