From 64317bc77e907f62a31875fc455ad9f35bbfa273 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Mon, 23 Dec 2024 17:10:55 +0000 Subject: [PATCH 01/24] basic computations skipping model working in GP comp --- .../client_ivc/mock_circuit_producer.hpp | 7 +- .../cpp/src/barretenberg/constants.hpp | 7 +- .../cpp/src/barretenberg/flavor/flavor.hpp | 2 + .../src/barretenberg/goblin/mock_circuits.hpp | 2 +- .../composer/permutation_lib.hpp | 61 ++++--- .../execution_trace/mega_execution_trace.hpp | 57 ++++-- .../library/grand_product_library.hpp | 162 ++++++++++++------ .../protogalaxy_prover_internal.hpp | 14 +- .../trace_to_polynomials.cpp | 4 + .../ultra_honk/mega_honk.test.cpp | 2 +- 10 files changed, 213 insertions(+), 105 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/mock_circuit_producer.hpp b/barretenberg/cpp/src/barretenberg/client_ivc/mock_circuit_producer.hpp index b2ba3f3656d..6d7e7910fd4 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/mock_circuit_producer.hpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/mock_circuit_producer.hpp @@ -119,9 +119,10 @@ class PrivateFunctionExecutionMockCircuitProducer { mock_databus.populate_kernel_databus(circuit); // populate databus inputs/outputs ivc.complete_kernel_circuit_logic(circuit); // complete with recursive verifiers etc } else { - bool use_large_circuit = large_first_app && (circuit_counter == 1); // first circuit is size 2^19 - GoblinMockCircuits::construct_mock_app_circuit(circuit, use_large_circuit); // construct mock app - mock_databus.populate_app_databus(circuit); // populate databus outputs + [[maybe_unused]] bool use_large_circuit = + large_first_app && (circuit_counter == 1); // first circuit is size 2^19 + GoblinMockCircuits::construct_mock_app_circuit(circuit, false); // construct mock app + mock_databus.populate_app_databus(circuit); // populate databus outputs } return circuit; } diff --git a/barretenberg/cpp/src/barretenberg/constants.hpp b/barretenberg/cpp/src/barretenberg/constants.hpp index 218761ae550..b2ecf89203c 100644 --- a/barretenberg/cpp/src/barretenberg/constants.hpp +++ b/barretenberg/cpp/src/barretenberg/constants.hpp @@ -13,9 +13,12 @@ static constexpr uint32_t CONST_PG_LOG_N = 20; static constexpr uint32_t CONST_ECCVM_LOG_N = 15; -static constexpr uint32_t MAX_LOOKUP_TABLES_SIZE = 75000; +// static constexpr uint32_t MAX_LOOKUP_TABLES_SIZE = 75000; -static constexpr uint32_t MAX_DATABUS_SIZE = 10000; +// static constexpr uint32_t MAX_DATABUS_SIZE = 10000; +static constexpr uint32_t MAX_LOOKUP_TABLES_SIZE = 8; + +static constexpr uint32_t MAX_DATABUS_SIZE = 2; // The number of entries in ProverPolynomials reserved for randomness intended to mask witness commitments, witness // evaluation at the sumcheck challenge, and, if necessary, the evaluation of the corresponding shift diff --git a/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp b/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp index eb3fa6a5994..6b64495c09d 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp @@ -125,6 +125,8 @@ template class ProvingKey_ { // Ranges of the form [start, end) where witnesses have non-zero values (hence the execution trace is "active") std::vector> active_block_ranges; + // The actual polynomial indices corresposponding to the active block ranges + std::vector active_idxs; ProvingKey_() = default; ProvingKey_(const size_t dyadic_circuit_size, diff --git a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp index 237e51a46d7..978c41933fe 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp @@ -191,7 +191,7 @@ class GoblinMockCircuits { { PROFILE_THIS(); - add_some_ecc_op_gates(builder); + // add_some_ecc_op_gates(builder); MockCircuits::construct_arithmetic_circuit(builder); } diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/composer/permutation_lib.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/composer/permutation_lib.hpp index d391d425af3..1ce196e69b4 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/composer/permutation_lib.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/composer/permutation_lib.hpp @@ -224,33 +224,44 @@ void compute_honk_style_permutation_lagrange_polynomials_from_mapping( using FF = typename Flavor::FF; const size_t num_gates = proving_key->circuit_size; + size_t domain_size = proving_key->active_idxs.size(); + size_t num_threads = calculate_num_threads(domain_size, /*min_iterations_per_thread=*/1 << 5); + size_t thread_size = domain_size / num_threads; + size_t leftover = domain_size % num_threads; + size_t wire_idx = 0; for (auto& current_permutation_poly : permutation_polynomials) { - ITERATE_OVER_DOMAIN_START(proving_key->evaluation_domain); - auto idx = static_cast(i); - const auto& current_row_idx = permutation_mappings[wire_idx].row_idx[idx]; - const auto& current_col_idx = permutation_mappings[wire_idx].col_idx[idx]; - const auto& current_is_tag = permutation_mappings[wire_idx].is_tag[idx]; - const auto& current_is_public_input = permutation_mappings[wire_idx].is_public_input[idx]; - if (current_is_public_input) { - // We intentionally want to break the cycles of the public input variables. - // During the witness generation, the left and right wire polynomials at idx i contain the i-th public - // input. The CyclicPermutation created for these variables always start with (i) -> (n+i), followed by - // the indices of the variables in the "real" gates. We make i point to -(i+1), so that the only way of - // repairing the cycle is add the mapping - // -(i+1) -> (n+i) - // These indices are chosen so they can easily be computed by the verifier. They can expect the running - // product to be equal to the "public input delta" that is computed in - current_permutation_poly.at(i) = -FF(current_row_idx + 1 + num_gates * current_col_idx); - } else if (current_is_tag) { - // Set evaluations to (arbitrary) values disjoint from non-tag values - current_permutation_poly.at(i) = num_gates * Flavor::NUM_WIRES + current_row_idx; - } else { - // For the regular permutation we simply point to the next location by setting the evaluation to its - // idx - current_permutation_poly.at(i) = FF(current_row_idx + num_gates * current_col_idx); - } - ITERATE_OVER_DOMAIN_END; + parallel_for(num_threads, [&](size_t j) { + const size_t start = j * thread_size; + const size_t end = (j == num_threads - 1) ? (j + 1) * thread_size + leftover : (j + 1) * thread_size; + for (size_t i = start; i < end; ++i) { + size_t poly_idx = proving_key->active_idxs[i]; + auto idx = static_cast(poly_idx); + const auto& current_row_idx = permutation_mappings[wire_idx].row_idx[idx]; + const auto& current_col_idx = permutation_mappings[wire_idx].col_idx[idx]; + const auto& current_is_tag = permutation_mappings[wire_idx].is_tag[idx]; + const auto& current_is_public_input = permutation_mappings[wire_idx].is_public_input[idx]; + if (current_is_public_input) { + // We intentionally want to break the cycles of the public input variables. + // During the witness generation, the left and right wire polynomials at idx i contain the i-th + // public input. The CyclicPermutation created for these variables always start with (i) -> (n+i), + // followed by the indices of the variables in the "real" gates. We make i point to + // -(i+1), so that the only way of repairing the cycle is add the mapping + // -(i+1) -> (n+i) + // These indices are chosen so they can easily be computed by the verifier. They can expect + // the running product to be equal to the "public input delta" that is computed + // in + current_permutation_poly.at(poly_idx) = -FF(current_row_idx + 1 + num_gates * current_col_idx); + } else if (current_is_tag) { + // Set evaluations to (arbitrary) values disjoint from non-tag values + current_permutation_poly.at(poly_idx) = num_gates * Flavor::NUM_WIRES + current_row_idx; + } else { + // For the regular permutation we simply point to the next location by setting the + // evaluation to its idx + current_permutation_poly.at(poly_idx) = FF(current_row_idx + num_gates * current_col_idx); + } + } + }); wire_idx++; } } diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/execution_trace/mega_execution_trace.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/execution_trace/mega_execution_trace.hpp index e1d31a9fac1..157ba16e49b 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/execution_trace/mega_execution_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/execution_trace/mega_execution_trace.hpp @@ -240,6 +240,21 @@ class MegaExecutionTraceBlocks : public MegaTraceBlockData { inline static const std::vector selector_names = {}; }; +/** + * @brief A tiny structuring (for testing without recursive verifications only) + */ +static constexpr TraceStructure MICRO_TEST_STRUCTURE{ .ecc_op = 5, + .busread = 5, + .lookup = 5, + .pub_inputs = 5, + .arithmetic = 10, + .delta_range = 2, + .elliptic = 2, + .aux = 2, + .poseidon2_external = 2, + .poseidon2_internal = 3, + .overflow = 0 }; + /** * @brief A tiny structuring (for testing without recursive verifications only) */ @@ -275,17 +290,39 @@ static constexpr TraceStructure SMALL_TEST_STRUCTURE{ .ecc_op = 1 << 14, * @brief A minimal structuring specifically tailored to the medium complexity transaction of the Client IVC * benchmark. */ -static constexpr TraceStructure CLIENT_IVC_BENCH_STRUCTURE{ .ecc_op = 1 << 10, - .busread = 1 << 7, - .lookup = 72000, - .pub_inputs = 1 << 7, - .arithmetic = 198000, - .delta_range = 90000, - .elliptic = 9000, - .aux = 136000, - .poseidon2_external = 2500, - .poseidon2_internal = 14000, +// static constexpr TraceStructure CLIENT_IVC_BENCH_STRUCTURE{ .ecc_op = 1 << 10, +// .busread = 1 << 6, +// .lookup = 36000, +// .pub_inputs = 1 << 6, +// .arithmetic = 84000, +// .delta_range = 45000, +// .elliptic = 9000, +// .aux = 68000, +// .poseidon2_external = 2500, +// .poseidon2_internal = 14000, +// .overflow = 0 }; +static constexpr TraceStructure CLIENT_IVC_BENCH_STRUCTURE{ .ecc_op = 1 << 11, + .busread = 1 << 8, + .lookup = 144000, + .pub_inputs = 1 << 8, + .arithmetic = 396000, + .delta_range = 180000, + .elliptic = 18000, + .aux = 272000, + .poseidon2_external = 5000, + .poseidon2_internal = 28000, .overflow = 0 }; +// static constexpr TraceStructure CLIENT_IVC_BENCH_STRUCTURE{ .ecc_op = 1 << 10, +// .busread = 1 << 7, +// .lookup = 72000, +// .pub_inputs = 1 << 7, +// .arithmetic = 198000, +// .delta_range = 90000, +// .elliptic = 9000, +// .aux = 136000, +// .poseidon2_external = 2500, +// .poseidon2_internal = 14000, +// .overflow = 0 }; /** * @brief An example structuring of size 2^18. diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp index ee7eeb3c437..5c2046ac8ef 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp @@ -69,7 +69,8 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, // the permutation grand product does not need to be computed beyond the index of the last active wire size_t domain_size = size_override == 0 ? full_polynomials.get_polynomial_size() : size_override; - const size_t num_threads = domain_size >= get_num_cpus_pow2() ? get_num_cpus_pow2() : 1; + const size_t num_threads = 1; + // const size_t num_threads = domain_size >= get_num_cpus_pow2() ? get_num_cpus_pow2() : 1; const size_t block_size = domain_size / num_threads; const size_t final_idx = domain_size - 1; @@ -81,6 +82,8 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, const size_t end = (thread_idx == num_threads - 1) ? final_idx : (thread_idx + 1) * block_size; idx_bounds.push_back(std::make_pair(start, end)); } + info("idx_bounds.start = ", idx_bounds[0].first); + info("idx_bounds.end = ", idx_bounds[0].second); // Allocate numerator/denominator polynomials that will serve as scratch space // TODO(zac) we can re-use the permutation polynomial as the numerator polynomial. Reduces readability @@ -96,27 +99,44 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, }); }; + for (auto range : active_block_ranges) { + info("start = ", range.first); + info("end = ", range.second); + } + // Step (1) // Populate `numerator` and `denominator` with the algebra described by Relation - FF gamma_fourth = relation_parameters.gamma.pow(4); - parallel_for(num_threads, [&](size_t thread_idx) { - typename Flavor::AllValues row; - const size_t start = idx_bounds[thread_idx].first; - const size_t end = idx_bounds[thread_idx].second; - for (size_t i = start; i < end; ++i) { - if (check_is_active(i)) { - // TODO(https://github.com/AztecProtocol/barretenberg/issues/940):consider avoiding get_row if possible. - row = full_polynomials.get_row(i); - numerator.at(i) = - GrandProdRelation::template compute_grand_product_numerator(row, relation_parameters); - denominator.at(i) = GrandProdRelation::template compute_grand_product_denominator( - row, relation_parameters); - } else { - numerator.at(i) = gamma_fourth; - denominator.at(i) = gamma_fourth; + FF gamma_fourth = FF(1); + // FF gamma_fourth = relation_parameters.gamma.pow(4); + { + PROFILE_THIS_NAME("GP step 1"); + parallel_for(num_threads, [&](size_t thread_idx) { + typename Flavor::AllValues row; + const size_t start = idx_bounds[thread_idx].first; + const size_t end = idx_bounds[thread_idx].second; + for (size_t i = start; i < end; ++i) { + if (check_is_active(i)) { + // TODO(https://github.com/AztecProtocol/barretenberg/issues/940):consider avoiding get_row if + // possible. + row = full_polynomials.get_row(i); + numerator.at(i) = GrandProdRelation::template compute_grand_product_numerator( + row, relation_parameters); + denominator.at(i) = GrandProdRelation::template compute_grand_product_denominator( + row, relation_parameters); + if (numerator[i] == gamma_fourth || denominator[i] == gamma_fourth) { + info("UH OH!, num = ", numerator[i], ", denom = ", denominator[i]); + } + } else { + numerator.at(i) = gamma_fourth; + denominator.at(i) = gamma_fourth; + if (!(numerator[i] == gamma_fourth && denominator[i] == gamma_fourth)) { + info("OH NO!, idx = ", i); + } + } + info("numerator(", i, ") = ", numerator[i]); } - } - }); + }); + } DEBUG_LOG_ALL(numerator.coeffs()); DEBUG_LOG_ALL(denominator.coeffs()); @@ -136,40 +156,60 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, std::vector partial_numerators(num_threads); std::vector partial_denominators(num_threads); - parallel_for(num_threads, [&](size_t thread_idx) { - const size_t start = idx_bounds[thread_idx].first; - const size_t end = idx_bounds[thread_idx].second; - for (size_t i = start; i < end - 1; ++i) { - numerator.at(i + 1) *= numerator[i]; - denominator.at(i + 1) *= denominator[i]; - } - partial_numerators[thread_idx] = numerator[end - 1]; - partial_denominators[thread_idx] = denominator[end - 1]; - }); - - DEBUG_LOG_ALL(partial_numerators); - DEBUG_LOG_ALL(partial_denominators); + { + PROFILE_THIS_NAME("GP step 2.1"); + parallel_for(num_threads, [&](size_t thread_idx) { + const size_t start = idx_bounds[thread_idx].first; + const size_t end = idx_bounds[thread_idx].second; + for (size_t i = start; i < end - 1; ++i) { + if (check_is_active(i + 1)) { + numerator.at(i + 1) *= numerator[i]; + denominator.at(i + 1) *= denominator[i]; + // info("active"); + } else { + numerator.at(i + 1) = numerator[i]; + denominator.at(i + 1) = denominator[i]; + // info("inactive"); + } + // info("num(", i + 1, ") = ", numerator[i + 1]); + } + partial_numerators[thread_idx] = numerator[end - 1]; + partial_denominators[thread_idx] = denominator[end - 1]; + }); - parallel_for(num_threads, [&](size_t thread_idx) { - const size_t start = idx_bounds[thread_idx].first; - const size_t end = idx_bounds[thread_idx].second; - if (thread_idx > 0) { - FF numerator_scaling = 1; - FF denominator_scaling = 1; + DEBUG_LOG_ALL(partial_numerators); + DEBUG_LOG_ALL(partial_denominators); + } + { + PROFILE_THIS_NAME("GP step 2.2"); + parallel_for(num_threads, [&](size_t thread_idx) { + const size_t start = idx_bounds[thread_idx].first; + const size_t end = idx_bounds[thread_idx].second; + if (thread_idx > 0) { + FF numerator_scaling = 1; + FF denominator_scaling = 1; - for (size_t j = 0; j < thread_idx; ++j) { - numerator_scaling *= partial_numerators[j]; - denominator_scaling *= partial_denominators[j]; - } - for (size_t i = start; i < end; ++i) { - numerator.at(i) = numerator[i] * numerator_scaling; - denominator.at(i) = denominator[i] * denominator_scaling; + for (size_t j = 0; j < thread_idx; ++j) { + numerator_scaling *= partial_numerators[j]; + denominator_scaling *= partial_denominators[j]; + } + for (size_t i = start; i < end; ++i) { + if (check_is_active(i)) { + numerator.at(i) = numerator[i] * numerator_scaling; + denominator.at(i) = denominator[i] * denominator_scaling; + // info("active num(", i, ") = ", numerator[i]); + } else { + numerator.at(i) = numerator[i - 1]; + denominator.at(i) = denominator[i - 1]; + // info("inactive num(", i, ") = ", numerator[i]); + } + } } - } - // Final step: invert denominator - FF::batch_invert(std::span{ &denominator.data()[start], end - start }); - }); + // Final step: invert denominator + FF::batch_invert(std::span{ &denominator.data()[start], end - start }); + }); + } DEBUG_LOG_ALL(numerator.coeffs()); DEBUG_LOG_ALL(denominator.coeffs()); @@ -179,13 +219,23 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, // We have a 'virtual' 0 at the start (as this is a to-be-shifted polynomial) ASSERT(grand_product_polynomial.start_index() == 1); - parallel_for(num_threads, [&](size_t thread_idx) { - const size_t start = idx_bounds[thread_idx].first; - const size_t end = idx_bounds[thread_idx].second; - for (size_t i = start; i < end; ++i) { - grand_product_polynomial.at(i + 1) = numerator[i] * denominator[i]; - } - }); + { + PROFILE_THIS_NAME("GP step 3"); + parallel_for(num_threads, [&](size_t thread_idx) { + const size_t start = idx_bounds[thread_idx].first; + const size_t end = idx_bounds[thread_idx].second; + for (size_t i = end; i-- > start;) { + if (check_is_active(i + 1)) { + grand_product_polynomial.at(i + 1) = numerator[i] * denominator[i]; + } else { + // WORKTODO: i+2 should be fine bc of the last_wire_idx mechanism but ensure it works in all cases + grand_product_polynomial.at(i + 1) = grand_product_polynomial[i + 2]; + } + info("active = ", check_is_active(i + 1)); + info("GP(", i + 1, ") = ", grand_product_polynomial.at(i + 1)); + } + }); + } DEBUG_LOG_ALL(grand_product_polynomial.coeffs()); } diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover_internal.hpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover_internal.hpp index 221d732a796..0acc9469143 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover_internal.hpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover_internal.hpp @@ -136,16 +136,16 @@ template class ProtogalaxyProverInternal { * representing the sum f_0(ω) + α_j*g(ω) where f_0 represents the full honk evaluation at row 0, g(ω) is the * linearly dependent subrelation and α_j is its corresponding batching challenge. */ - std::vector compute_row_evaluations(const ProverPolynomials& polynomials, - const RelationSeparator& alphas_, - const RelationParameters& relation_parameters) + Polynomial compute_row_evaluations(const ProverPolynomials& polynomials, + const RelationSeparator& alphas_, + const RelationParameters& relation_parameters) { PROFILE_THIS_NAME("ProtogalaxyProver_::compute_row_evaluations"); const size_t polynomial_size = polynomials.get_polynomial_size(); - std::vector aggregated_relation_evaluations(polynomial_size); + Polynomial aggregated_relation_evaluations(polynomial_size); const std::array alphas = [&alphas_]() { std::array tmp; @@ -176,13 +176,13 @@ template class ProtogalaxyProverInternal { RelationUtils::accumulate_relation_evaluations(row, relation_parameters, FF(1)); // Sum against challenges alpha - aggregated_relation_evaluations[idx] = process_subrelation_evaluations( + aggregated_relation_evaluations.at(idx) = process_subrelation_evaluations( evals, alphas, linearly_dependent_contribution_accumulators[thread_idx]); } } }); - aggregated_relation_evaluations[0] += sum(linearly_dependent_contribution_accumulators); + aggregated_relation_evaluations.at(0) += sum(linearly_dependent_contribution_accumulators); return aggregated_relation_evaluations; } @@ -263,7 +263,7 @@ template class ProtogalaxyProverInternal { */ static std::vector construct_perturbator_coefficients(std::span betas, std::span deltas, - const std::vector& full_honk_evaluations) + const Polynomial& full_honk_evaluations) { const size_t width = full_honk_evaluations.size() / 2; diff --git a/barretenberg/cpp/src/barretenberg/trace_to_polynomials/trace_to_polynomials.cpp b/barretenberg/cpp/src/barretenberg/trace_to_polynomials/trace_to_polynomials.cpp index f9d3405d2f8..2321dcb7736 100644 --- a/barretenberg/cpp/src/barretenberg/trace_to_polynomials/trace_to_polynomials.cpp +++ b/barretenberg/cpp/src/barretenberg/trace_to_polynomials/trace_to_polynomials.cpp @@ -103,8 +103,12 @@ typename TraceToPolynomials::TraceData TraceToPolynomials::const // Save ranges over which the blocks are "active" for use in structured commitments if constexpr (IsUltraFlavor) { // Mega and Ultra + PROFILE_THIS_NAME("construct_active_indices"); if (block.size() > 0) { proving_key.active_block_ranges.emplace_back(offset, offset + block.size()); + for (uint32_t i = offset; i < offset + block.size(); ++i) { + proving_key.active_idxs.push_back(i); + } } } diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp index 0804bb3c97b..21b04dfe525 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp @@ -120,7 +120,7 @@ TYPED_TEST(MegaHonkTests, BasicStructured) GoblinMockCircuits::construct_simple_circuit(builder); // Construct and verify Honk proof using a structured trace - TraceSettings trace_settings{ SMALL_TEST_STRUCTURE }; + TraceSettings trace_settings{ MICRO_TEST_STRUCTURE }; auto proving_key = std::make_shared>(builder, trace_settings); Prover prover(proving_key); auto verification_key = std::make_shared(proving_key->proving_key); From 0ab2078ed3152165a76b842c741151f9823c5a44 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Mon, 23 Dec 2024 20:50:49 +0000 Subject: [PATCH 02/24] WiP things working before switch to active idxs loops --- .../cpp/src/barretenberg/constants.hpp | 9 +- .../library/grand_product_library.hpp | 97 +++++++++++++------ 2 files changed, 70 insertions(+), 36 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/constants.hpp b/barretenberg/cpp/src/barretenberg/constants.hpp index b2ecf89203c..33f23432860 100644 --- a/barretenberg/cpp/src/barretenberg/constants.hpp +++ b/barretenberg/cpp/src/barretenberg/constants.hpp @@ -13,12 +13,11 @@ static constexpr uint32_t CONST_PG_LOG_N = 20; static constexpr uint32_t CONST_ECCVM_LOG_N = 15; -// static constexpr uint32_t MAX_LOOKUP_TABLES_SIZE = 75000; +static constexpr uint32_t MAX_LOOKUP_TABLES_SIZE = 75000; +// static constexpr uint32_t MAX_LOOKUP_TABLES_SIZE = 8; -// static constexpr uint32_t MAX_DATABUS_SIZE = 10000; -static constexpr uint32_t MAX_LOOKUP_TABLES_SIZE = 8; - -static constexpr uint32_t MAX_DATABUS_SIZE = 2; +static constexpr uint32_t MAX_DATABUS_SIZE = 10000; +// static constexpr uint32_t MAX_DATABUS_SIZE = 2; // The number of entries in ProverPolynomials reserved for randomness intended to mask witness commitments, witness // evaluation at the sumcheck challenge, and, if necessary, the evaluation of the corresponding shift diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp index 5c2046ac8ef..ed2607f7dc4 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp @@ -61,6 +61,13 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, { PROFILE_THIS_NAME("compute_grand_product"); + std::vector active_idxs; + for (auto& range : active_block_ranges) { + for (size_t i = range.first; i < range.second; ++i) { + active_idxs.push_back(i); + } + } + using FF = typename Flavor::FF; using Polynomial = typename Flavor::Polynomial; using Accumulator = std::tuple_element_t<0, typename GrandProdRelation::SumcheckArrayOfValuesOverSubrelations>; @@ -69,21 +76,45 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, // the permutation grand product does not need to be computed beyond the index of the last active wire size_t domain_size = size_override == 0 ? full_polynomials.get_polynomial_size() : size_override; - const size_t num_threads = 1; - // const size_t num_threads = domain_size >= get_num_cpus_pow2() ? get_num_cpus_pow2() : 1; - const size_t block_size = domain_size / num_threads; - const size_t final_idx = domain_size - 1; - - // Cumpute the index bounds for each thread for reuse in the computations below + // const size_t num_threads = 4; std::vector> idx_bounds; - idx_bounds.reserve(num_threads); - for (size_t thread_idx = 0; thread_idx < num_threads; ++thread_idx) { - const size_t start = thread_idx * block_size; - const size_t end = (thread_idx == num_threads - 1) ? final_idx : (thread_idx + 1) * block_size; - idx_bounds.push_back(std::make_pair(start, end)); + const size_t num_threads = calculate_num_threads(domain_size, /*min_iterations_per_thread=*/1 << 14); + { + info("num_threads = ", num_threads); + // const size_t num_threads = domain_size >= get_num_cpus_pow2() ? get_num_cpus_pow2() : 1; + const size_t block_size = domain_size / num_threads; + const size_t final_idx = domain_size - 1; + + // Cumpute the index bounds for each thread for reuse in the computations below + idx_bounds.reserve(num_threads); + for (size_t thread_idx = 0; thread_idx < num_threads; ++thread_idx) { + const size_t start = thread_idx * block_size; + const size_t end = (thread_idx == num_threads - 1) ? final_idx : (thread_idx + 1) * block_size; + idx_bounds.push_back(std::make_pair(start, end)); + info("idx_bounds.start = ", start); + info("idx_bounds.end = ", end); + } + } + + std::vector> active_idx_bounds; + { + size_t domain_size = active_idxs.size(); + const size_t num_threads = calculate_num_threads(domain_size, /*min_iterations_per_thread=*/1 << 5); + // info("num_threads = ", num_threads); + // const size_t num_threads = domain_size >= get_num_cpus_pow2() ? get_num_cpus_pow2() : 1; + const size_t block_size = domain_size / num_threads; + const size_t final_idx = domain_size - 1; + + // Cumpute the index bounds for each thread for reuse in the computations below + active_idx_bounds.reserve(num_threads); + for (size_t thread_idx = 0; thread_idx < num_threads; ++thread_idx) { + const size_t start = thread_idx * block_size; + const size_t end = (thread_idx == num_threads - 1) ? final_idx : (thread_idx + 1) * block_size; + active_idx_bounds.push_back(std::make_pair(start, end)); + // info("idx_bounds.start = ", start); + // info("idx_bounds.end = ", end); + } } - info("idx_bounds.start = ", idx_bounds[0].first); - info("idx_bounds.end = ", idx_bounds[0].second); // Allocate numerator/denominator polynomials that will serve as scratch space // TODO(zac) we can re-use the permutation polynomial as the numerator polynomial. Reduces readability @@ -106,8 +137,6 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, // Step (1) // Populate `numerator` and `denominator` with the algebra described by Relation - FF gamma_fourth = FF(1); - // FF gamma_fourth = relation_parameters.gamma.pow(4); { PROFILE_THIS_NAME("GP step 1"); parallel_for(num_threads, [&](size_t thread_idx) { @@ -123,17 +152,7 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, row, relation_parameters); denominator.at(i) = GrandProdRelation::template compute_grand_product_denominator( row, relation_parameters); - if (numerator[i] == gamma_fourth || denominator[i] == gamma_fourth) { - info("UH OH!, num = ", numerator[i], ", denom = ", denominator[i]); - } - } else { - numerator.at(i) = gamma_fourth; - denominator.at(i) = gamma_fourth; - if (!(numerator[i] == gamma_fourth && denominator[i] == gamma_fourth)) { - info("OH NO!, idx = ", i); - } } - info("numerator(", i, ") = ", numerator[i]); } }); } @@ -199,8 +218,10 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, denominator.at(i) = denominator[i] * denominator_scaling; // info("active num(", i, ") = ", numerator[i]); } else { - numerator.at(i) = numerator[i - 1]; - denominator.at(i) = denominator[i - 1]; + // numerator.at(i) = numerator[i - 1]; + // denominator.at(i) = denominator[i - 1]; + numerator.at(i) = numerator[i] * numerator_scaling; + denominator.at(i) = denominator[i] * denominator_scaling; // info("inactive num(", i, ") = ", numerator[i]); } } @@ -228,11 +249,25 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, if (check_is_active(i + 1)) { grand_product_polynomial.at(i + 1) = numerator[i] * denominator[i]; } else { - // WORKTODO: i+2 should be fine bc of the last_wire_idx mechanism but ensure it works in all cases - grand_product_polynomial.at(i + 1) = grand_product_polynomial[i + 2]; + // grand_product_polynomial.at(i + 1) = numerator[i] * denominator[i]; + // if (i + 2 >= end) { + // info("INVALID READ AT i+2!!!!!"); + // } + // WORKTODO: reading into adjacent entries in GP is no good because we could be reading into data + // being handled by another thread that has not populated those values yet. Need to find a way to + // make this independent of adjacent entries. grand_product_polynomial.at(i + 1) = + // grand_product_polynomial[i + 2]; + for (size_t j = 0; j < active_block_ranges.size() - 1; ++j) { + auto& ranges = active_block_ranges; + if (i + 1 >= ranges[j].second && i + 1 < ranges[j + 1].first) { + size_t val_idx = ranges[j + 1].first; + grand_product_polynomial.at(i + 1) = numerator[val_idx] * denominator[val_idx]; + break; + } + } } - info("active = ", check_is_active(i + 1)); - info("GP(", i + 1, ") = ", grand_product_polynomial.at(i + 1)); + // info("active = ", check_is_active(i + 1)); + // info("GP(", i + 1, ") = ", grand_product_polynomial.at(i + 1)); } }); } From 35d1c8dce08f9b6e7e409e844e9e4144e7e6f2f9 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Mon, 23 Dec 2024 21:09:32 +0000 Subject: [PATCH 03/24] using active idxs for GP step 1 --- .../library/grand_product_library.hpp | 55 ++++++++++--------- 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp index ed2607f7dc4..53d02665c38 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp @@ -61,13 +61,6 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, { PROFILE_THIS_NAME("compute_grand_product"); - std::vector active_idxs; - for (auto& range : active_block_ranges) { - for (size_t i = range.first; i < range.second; ++i) { - active_idxs.push_back(i); - } - } - using FF = typename Flavor::FF; using Polynomial = typename Flavor::Polynomial; using Accumulator = std::tuple_element_t<0, typename GrandProdRelation::SumcheckArrayOfValuesOverSubrelations>; @@ -76,6 +69,19 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, // the permutation grand product does not need to be computed beyond the index of the last active wire size_t domain_size = size_override == 0 ? full_polynomials.get_polynomial_size() : size_override; + std::vector active_idxs; + if (active_block_ranges.empty()) { + for (size_t i = 0; i < domain_size; ++i) { + active_idxs.push_back(i); + } + } else { + for (auto& range : active_block_ranges) { + for (size_t i = range.first; i < range.second; ++i) { + active_idxs.push_back(i); + } + } + } + // const size_t num_threads = 4; std::vector> idx_bounds; const size_t num_threads = calculate_num_threads(domain_size, /*min_iterations_per_thread=*/1 << 14); @@ -96,20 +102,18 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, } } + const size_t active_num_threads = calculate_num_threads(domain_size, /*min_iterations_per_thread=*/1 << 5); std::vector> active_idx_bounds; { size_t domain_size = active_idxs.size(); - const size_t num_threads = calculate_num_threads(domain_size, /*min_iterations_per_thread=*/1 << 5); - // info("num_threads = ", num_threads); - // const size_t num_threads = domain_size >= get_num_cpus_pow2() ? get_num_cpus_pow2() : 1; - const size_t block_size = domain_size / num_threads; + const size_t block_size = domain_size / active_num_threads; const size_t final_idx = domain_size - 1; // Cumpute the index bounds for each thread for reuse in the computations below - active_idx_bounds.reserve(num_threads); - for (size_t thread_idx = 0; thread_idx < num_threads; ++thread_idx) { + active_idx_bounds.reserve(active_num_threads); + for (size_t thread_idx = 0; thread_idx < active_num_threads; ++thread_idx) { const size_t start = thread_idx * block_size; - const size_t end = (thread_idx == num_threads - 1) ? final_idx : (thread_idx + 1) * block_size; + const size_t end = (thread_idx == active_num_threads - 1) ? final_idx : (thread_idx + 1) * block_size; active_idx_bounds.push_back(std::make_pair(start, end)); // info("idx_bounds.start = ", start); // info("idx_bounds.end = ", end); @@ -139,20 +143,19 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, // Populate `numerator` and `denominator` with the algebra described by Relation { PROFILE_THIS_NAME("GP step 1"); - parallel_for(num_threads, [&](size_t thread_idx) { + parallel_for(active_num_threads, [&](size_t thread_idx) { typename Flavor::AllValues row; - const size_t start = idx_bounds[thread_idx].first; - const size_t end = idx_bounds[thread_idx].second; + const size_t start = active_idx_bounds[thread_idx].first; + const size_t end = active_idx_bounds[thread_idx].second; for (size_t i = start; i < end; ++i) { - if (check_is_active(i)) { - // TODO(https://github.com/AztecProtocol/barretenberg/issues/940):consider avoiding get_row if - // possible. - row = full_polynomials.get_row(i); - numerator.at(i) = GrandProdRelation::template compute_grand_product_numerator( - row, relation_parameters); - denominator.at(i) = GrandProdRelation::template compute_grand_product_denominator( - row, relation_parameters); - } + // TODO(https://github.com/AztecProtocol/barretenberg/issues/940):consider avoiding get_row if + // possible. + size_t idx = active_idxs[i]; + row = full_polynomials.get_row(idx); // WORKTODO: implement get_row_for_permuation_argument? + numerator.at(idx) = + GrandProdRelation::template compute_grand_product_numerator(row, relation_parameters); + denominator.at(idx) = GrandProdRelation::template compute_grand_product_denominator( + row, relation_parameters); } }); } From 418f7bc077fa8728f49d8183574aaaffb5bb93b0 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Mon, 23 Dec 2024 22:29:23 +0000 Subject: [PATCH 04/24] fix --- .../plonk_honk_shared/library/grand_product_library.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp index 53d02665c38..f54c74b7a80 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp @@ -249,7 +249,8 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, const size_t start = idx_bounds[thread_idx].first; const size_t end = idx_bounds[thread_idx].second; for (size_t i = end; i-- > start;) { - if (check_is_active(i + 1)) { + // if (check_is_active(i + 1)) { + if (check_is_active(i)) { grand_product_polynomial.at(i + 1) = numerator[i] * denominator[i]; } else { // grand_product_polynomial.at(i + 1) = numerator[i] * denominator[i]; From 09ef41a10db317a4bca6f11ade65f53b0a02f261 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Mon, 23 Dec 2024 23:18:40 +0000 Subject: [PATCH 05/24] dont do any computation for num/denom in inactive regions --- .../library/grand_product_library.hpp | 22 +------------------ 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp index f54c74b7a80..d39cc14699f 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp @@ -187,13 +187,7 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, if (check_is_active(i + 1)) { numerator.at(i + 1) *= numerator[i]; denominator.at(i + 1) *= denominator[i]; - // info("active"); - } else { - numerator.at(i + 1) = numerator[i]; - denominator.at(i + 1) = denominator[i]; - // info("inactive"); } - // info("num(", i + 1, ") = ", numerator[i + 1]); } partial_numerators[thread_idx] = numerator[end - 1]; partial_denominators[thread_idx] = denominator[end - 1]; @@ -219,13 +213,6 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, if (check_is_active(i)) { numerator.at(i) = numerator[i] * numerator_scaling; denominator.at(i) = denominator[i] * denominator_scaling; - // info("active num(", i, ") = ", numerator[i]); - } else { - // numerator.at(i) = numerator[i - 1]; - // denominator.at(i) = denominator[i - 1]; - numerator.at(i) = numerator[i] * numerator_scaling; - denominator.at(i) = denominator[i] * denominator_scaling; - // info("inactive num(", i, ") = ", numerator[i]); } } } @@ -253,14 +240,7 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, if (check_is_active(i)) { grand_product_polynomial.at(i + 1) = numerator[i] * denominator[i]; } else { - // grand_product_polynomial.at(i + 1) = numerator[i] * denominator[i]; - // if (i + 2 >= end) { - // info("INVALID READ AT i+2!!!!!"); - // } - // WORKTODO: reading into adjacent entries in GP is no good because we could be reading into data - // being handled by another thread that has not populated those values yet. Need to find a way to - // make this independent of adjacent entries. grand_product_polynomial.at(i + 1) = - // grand_product_polynomial[i + 2]; + // Set the value in the inactive regions to the first active value in the active region that follows for (size_t j = 0; j < active_block_ranges.size() - 1; ++j) { auto& ranges = active_block_ranges; if (i + 1 >= ranges[j].second && i + 1 < ranges[j + 1].first) { From 72b215fc0741137cf461da9dd93d8bcd64521170 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Tue, 24 Dec 2024 16:33:57 +0000 Subject: [PATCH 06/24] fix build --- .../cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp index bcbd70090d6..2b692ab8110 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp @@ -137,7 +137,7 @@ template class ProtogalaxyTests : public testing::Test { decider_pk->proving_key.polynomials, decider_pk->alphas, decider_pk->relation_parameters); // Evaluations should be 0 for valid circuit - for (const auto& eval : full_honk_evals) { + for (const auto& eval : full_honk_evals.coeffs()) { EXPECT_EQ(eval, FF(0)); } } @@ -152,7 +152,11 @@ template class ProtogalaxyTests : public testing::Test { std::vector betas = { FF(5), FF(8), FF(11) }; std::vector deltas = { FF(2), FF(4), FF(8) }; std::vector full_honk_evaluations = { FF(1), FF(1), FF(1), FF(1), FF(1), FF(1), FF(1), FF(1) }; - auto perturbator = PGInternal::construct_perturbator_coefficients(betas, deltas, full_honk_evaluations); + [[maybe_unused]] Polynomial honk_evaluations_poly(full_honk_evaluations.size()); + for (auto [poly_val, val] : zip_view(honk_evaluations_poly.coeffs(), full_honk_evaluations)) { + poly_val = val; + } + auto perturbator = PGInternal::construct_perturbator_coefficients(betas, deltas, honk_evaluations_poly); std::vector expected_values = { FF(648), FF(936), FF(432), FF(64) }; EXPECT_EQ(perturbator.size(), 4); // log(size) + 1 for (size_t i = 0; i < perturbator.size(); i++) { From c36feaa51eecfb9938db617802305692e8ee2737 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Tue, 24 Dec 2024 17:04:56 +0000 Subject: [PATCH 07/24] fix PG tests --- .../cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp | 7 ++++++- .../protogalaxy_recursive_verifier.test.cpp | 8 +++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp index 2b692ab8110..a2ba1a1624d 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp @@ -564,7 +564,12 @@ template class ProtogalaxyTests : public testing::Test { EXPECT_TRUE(check_accumulator_target_sum_manual(prover_accumulator)); // Tamper with an accumulator polynomial - prover_accumulator->proving_key.polynomials.w_l.at(1) = FF::random_element(); + for (size_t i = 0; i < prover_accumulator->proving_key.circuit_size; ++i) { + if (prover_accumulator->proving_key.polynomials.q_arith[i] != 0) { + prover_accumulator->proving_key.polynomials.w_l.at(i) += 1; + break; + } + } EXPECT_FALSE(check_accumulator_target_sum_manual(prover_accumulator)); TupleOfKeys insts_2 = construct_keys(1); // just one decider key pair diff --git a/barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/protogalaxy_recursive_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/protogalaxy_recursive_verifier.test.cpp index 81586173b6c..912997bd0f1 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/protogalaxy_recursive_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/protogalaxy_recursive_verifier.test.cpp @@ -386,7 +386,13 @@ template class ProtogalaxyRecursiveTests : public tes auto verification_key = std::make_shared(prover_inst->proving_key); auto verifier_inst = std::make_shared(verification_key); - prover_accumulator->proving_key.polynomials.w_l.at(1) = FF::random_element(&engine); + // Tamper with a non-trivial wire value in the accumulator + for (size_t i = 0; i < prover_accumulator->proving_key.circuit_size; ++i) { + if (prover_accumulator->proving_key.polynomials.q_arith[i] != 0) { + prover_accumulator->proving_key.polynomials.w_l.at(i) += 1; + break; + } + } // Generate a folding proof with the incorrect polynomials which would result in the prover having the wrong // target sum From bd8a51105b8a2d6c282f075afdf75509af1fccef Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Tue, 24 Dec 2024 17:19:19 +0000 Subject: [PATCH 08/24] clean debug code to fix some tests --- .../cpp/src/barretenberg/goblin/mock_circuits.hpp | 2 +- .../execution_trace/mega_execution_trace.hpp | 15 --------------- .../barretenberg/ultra_honk/mega_honk.test.cpp | 9 +++++++-- 3 files changed, 8 insertions(+), 18 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp index 978c41933fe..237e51a46d7 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp @@ -191,7 +191,7 @@ class GoblinMockCircuits { { PROFILE_THIS(); - // add_some_ecc_op_gates(builder); + add_some_ecc_op_gates(builder); MockCircuits::construct_arithmetic_circuit(builder); } diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/execution_trace/mega_execution_trace.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/execution_trace/mega_execution_trace.hpp index 157ba16e49b..d339c0e06a1 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/execution_trace/mega_execution_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/execution_trace/mega_execution_trace.hpp @@ -240,21 +240,6 @@ class MegaExecutionTraceBlocks : public MegaTraceBlockData { inline static const std::vector selector_names = {}; }; -/** - * @brief A tiny structuring (for testing without recursive verifications only) - */ -static constexpr TraceStructure MICRO_TEST_STRUCTURE{ .ecc_op = 5, - .busread = 5, - .lookup = 5, - .pub_inputs = 5, - .arithmetic = 10, - .delta_range = 2, - .elliptic = 2, - .aux = 2, - .poseidon2_external = 2, - .poseidon2_internal = 3, - .overflow = 0 }; - /** * @brief A tiny structuring (for testing without recursive verifications only) */ diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp index 21b04dfe525..890c85517eb 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp @@ -120,7 +120,7 @@ TYPED_TEST(MegaHonkTests, BasicStructured) GoblinMockCircuits::construct_simple_circuit(builder); // Construct and verify Honk proof using a structured trace - TraceSettings trace_settings{ MICRO_TEST_STRUCTURE }; + TraceSettings trace_settings{ SMALL_TEST_STRUCTURE }; auto proving_key = std::make_shared>(builder, trace_settings); Prover prover(proving_key); auto verification_key = std::make_shared(proving_key->proving_key); @@ -390,7 +390,12 @@ TYPED_TEST(MegaHonkTests, PolySwap) auto proving_key_2 = std::make_shared(builder_copy, trace_settings); // Tamper with the polys of pkey 1 in such a way that verification should fail - proving_key_1->proving_key.polynomials.w_l.at(5) = 10; + for (size_t i = 0; i < proving_key_1->proving_key.circuit_size; ++i) { + if (proving_key_1->proving_key.polynomials.q_arith[i] != 0) { + proving_key_1->proving_key.polynomials.w_l.at(i) += 1; + break; + } + } // Swap the polys of the two proving keys; result should be pkey 1 is valid and pkey 2 should fail std::swap(proving_key_1->proving_key.polynomials, proving_key_2->proving_key.polynomials); From d9b43bb847735f3408187eff33af0e949af4158a Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Thu, 2 Jan 2025 21:00:02 +0000 Subject: [PATCH 09/24] test revision of gp method --- .../cpp/src/barretenberg/constants.hpp | 3 +- .../src/barretenberg/goblin/mock_circuits.hpp | 4 +- .../execution_trace/mega_execution_trace.hpp | 15 ++ .../library/grand_product_library.hpp | 225 ++++++++++++++++-- .../ultra_honk/mega_honk.test.cpp | 18 ++ 5 files changed, 247 insertions(+), 18 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/constants.hpp b/barretenberg/cpp/src/barretenberg/constants.hpp index 33f23432860..4091be5e4dd 100644 --- a/barretenberg/cpp/src/barretenberg/constants.hpp +++ b/barretenberg/cpp/src/barretenberg/constants.hpp @@ -14,9 +14,10 @@ static constexpr uint32_t CONST_PG_LOG_N = 20; static constexpr uint32_t CONST_ECCVM_LOG_N = 15; static constexpr uint32_t MAX_LOOKUP_TABLES_SIZE = 75000; -// static constexpr uint32_t MAX_LOOKUP_TABLES_SIZE = 8; static constexpr uint32_t MAX_DATABUS_SIZE = 10000; + +// static constexpr uint32_t MAX_LOOKUP_TABLES_SIZE = 8; // static constexpr uint32_t MAX_DATABUS_SIZE = 2; // The number of entries in ProverPolynomials reserved for randomness intended to mask witness commitments, witness diff --git a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp index 9a23c848af5..11b11bd64b0 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp @@ -190,8 +190,8 @@ class GoblinMockCircuits { static void construct_simple_circuit(MegaBuilder& builder) { PROFILE_THIS(); - - add_some_ecc_op_gates(builder); + // DEBUG + // add_some_ecc_op_gates(builder); MockCircuits::construct_arithmetic_circuit(builder); } diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/execution_trace/mega_execution_trace.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/execution_trace/mega_execution_trace.hpp index d339c0e06a1..2216b0f3a7d 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/execution_trace/mega_execution_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/execution_trace/mega_execution_trace.hpp @@ -240,6 +240,21 @@ class MegaExecutionTraceBlocks : public MegaTraceBlockData { inline static const std::vector selector_names = {}; }; +/** + * @brief A micro structuring (for testing without recursive verifications only) + */ +static constexpr TraceStructure MICRO_TEST_STRUCTURE{ .ecc_op = 5, + .busread = 5, + .lookup = 2, + .pub_inputs = 1, + .arithmetic = 8, + .delta_range = 2, + .elliptic = 2, + .aux = 2, + .poseidon2_external = 2, + .poseidon2_internal = 2, + .overflow = 0 }; + /** * @brief A tiny structuring (for testing without recursive verifications only) */ diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp index d39cc14699f..655975e0af7 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp @@ -54,10 +54,10 @@ namespace bb { * @param size_override optional size of the domain; otherwise based on dyadic polynomial domain */ template -void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, - bb::RelationParameters& relation_parameters, - size_t size_override = 0, - std::vector> active_block_ranges = {}) +void compute_grand_product_old(typename Flavor::ProverPolynomials& full_polynomials, + bb::RelationParameters& relation_parameters, + size_t size_override = 0, + std::vector> active_block_ranges = {}) { PROFILE_THIS_NAME("compute_grand_product"); @@ -143,21 +143,45 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, // Populate `numerator` and `denominator` with the algebra described by Relation { PROFILE_THIS_NAME("GP step 1"); - parallel_for(active_num_threads, [&](size_t thread_idx) { + parallel_for(num_threads, [&](size_t thread_idx) { typename Flavor::AllValues row; - const size_t start = active_idx_bounds[thread_idx].first; - const size_t end = active_idx_bounds[thread_idx].second; + const size_t start = idx_bounds[thread_idx].first; + const size_t end = idx_bounds[thread_idx].second; for (size_t i = start; i < end; ++i) { - // TODO(https://github.com/AztecProtocol/barretenberg/issues/940):consider avoiding get_row if - // possible. - size_t idx = active_idxs[i]; - row = full_polynomials.get_row(idx); // WORKTODO: implement get_row_for_permuation_argument? - numerator.at(idx) = - GrandProdRelation::template compute_grand_product_numerator(row, relation_parameters); - denominator.at(idx) = GrandProdRelation::template compute_grand_product_denominator( - row, relation_parameters); + if (check_is_active(i)) { + // TODO(https://github.com/AztecProtocol/barretenberg/issues/940):consider avoiding get_row if + // possible. + row = full_polynomials.get_row(i); + numerator.at(i) = GrandProdRelation::template compute_grand_product_numerator( + row, relation_parameters); + denominator.at(i) = GrandProdRelation::template compute_grand_product_denominator( + row, relation_parameters); + } else { + numerator.at(i) = 1; + denominator.at(i) = 1; + } + info("num = ", numerator.at(i)); + info("den = ", denominator.at(i)); } }); + // parallel_for(active_num_threads, [&](size_t thread_idx) { + // typename Flavor::AllValues row; + // const size_t start = active_idx_bounds[thread_idx].first; + // const size_t end = active_idx_bounds[thread_idx].second; + // for (size_t i = start; i < end; ++i) { + // // TODO(https://github.com/AztecProtocol/barretenberg/issues/940):consider avoiding get_row if + // // possible. + // size_t idx = active_idxs[i]; + // row = full_polynomials.get_row(idx); // WORKTODO: implement get_row_for_permuation_argument? + // numerator.at(idx) = + // GrandProdRelation::template compute_grand_product_numerator(row, + // relation_parameters); + // denominator.at(idx) = GrandProdRelation::template compute_grand_product_denominator( + // row, relation_parameters); + // info("num = ", numerator.at(idx)); + // info("den = ", denominator.at(idx)); + // } + // }); } DEBUG_LOG_ALL(numerator.coeffs()); @@ -179,6 +203,7 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, std::vector partial_denominators(num_threads); { + info("GP step 2.1"); PROFILE_THIS_NAME("GP step 2.1"); parallel_for(num_threads, [&](size_t thread_idx) { const size_t start = idx_bounds[thread_idx].first; @@ -188,6 +213,8 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, numerator.at(i + 1) *= numerator[i]; denominator.at(i + 1) *= denominator[i]; } + info("num = ", numerator.at(i + 1)); + info("den = ", denominator.at(i + 1)); } partial_numerators[thread_idx] = numerator[end - 1]; partial_denominators[thread_idx] = denominator[end - 1]; @@ -259,6 +286,174 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, DEBUG_LOG_ALL(grand_product_polynomial.coeffs()); } +template +void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, + bb::RelationParameters& relation_parameters, + size_t size_override = 0, + std::vector> active_block_ranges = {}) +{ + PROFILE_THIS_NAME("compute_grand_product"); + + for (auto range : active_block_ranges) { + info("start = ", range.first); + info("end = ", range.second); + } + + using FF = typename Flavor::FF; + using Polynomial = typename Flavor::Polynomial; + using Accumulator = std::tuple_element_t<0, typename GrandProdRelation::SumcheckArrayOfValuesOverSubrelations>; + + // Set the domain over which the grand product must be computed. This may be less than the dyadic circuit size, e.g + // the permutation grand product does not need to be computed beyond the index of the last active wire + size_t domain_size = size_override == 0 ? full_polynomials.get_polynomial_size() : size_override; + + const size_t num_threads = domain_size >= get_num_cpus_pow2() ? get_num_cpus_pow2() : 1; + const size_t block_size = domain_size / num_threads; + const size_t final_idx = domain_size - 1; + + // Cumpute the index bounds for each thread for reuse in the computations below + std::vector> idx_bounds; + idx_bounds.reserve(num_threads); + for (size_t thread_idx = 0; thread_idx < num_threads; ++thread_idx) { + const size_t start = thread_idx * block_size; + const size_t end = (thread_idx == num_threads - 1) ? final_idx : (thread_idx + 1) * block_size; + idx_bounds.push_back(std::make_pair(start, end)); + } + + // Allocate numerator/denominator polynomials that will serve as scratch space + // TODO(zac) we can re-use the permutation polynomial as the numerator polynomial. Reduces readability + Polynomial numerator{ domain_size, domain_size }; + Polynomial denominator{ domain_size, domain_size }; + + auto check_is_active = [&](size_t idx) { + if (active_block_ranges.empty()) { + return true; + } + return std::any_of(active_block_ranges.begin(), active_block_ranges.end(), [idx](const auto& range) { + return idx >= range.first && idx < range.second; + }); + }; + + // Step (1) + // Populate `numerator` and `denominator` with the algebra described by Relation + // FF gamma_fourth = relation_parameters.gamma.pow(4); + parallel_for(num_threads, [&](size_t thread_idx) { + typename Flavor::AllValues row; + const size_t start = idx_bounds[thread_idx].first; + const size_t end = idx_bounds[thread_idx].second; + for (size_t i = start; i < end; ++i) { + if (check_is_active(i)) { + // TODO(https://github.com/AztecProtocol/barretenberg/issues/940):consider avoiding get_row if possible. + row = full_polynomials.get_row(i); + numerator.at(i) = + GrandProdRelation::template compute_grand_product_numerator(row, relation_parameters); + denominator.at(i) = GrandProdRelation::template compute_grand_product_denominator( + row, relation_parameters); + } else { + numerator.at(i) = 1; + denominator.at(i) = 1; + } + } + }); + + DEBUG_LOG_ALL(numerator.coeffs()); + DEBUG_LOG_ALL(denominator.coeffs()); + + // Step (2) + // Compute the accumulating product of the numerator and denominator terms. + // This step is split into three parts for efficient multithreading: + // (i) compute ∏ A(j), ∏ B(j) subproducts for each thread + // (ii) compute scaling factor required to convert each subproduct into a single running product + // (ii) combine subproducts into a single running product + // + // For example, consider 4 threads and a size-8 numerator { a0, a1, a2, a3, a4, a5, a6, a7 } + // (i) Each thread computes 1 element of N = {{ a0, a0a1 }, { a2, a2a3 }, { a4, a4a5 }, { a6, a6a7 }} + // (ii) Take partial products P = { 1, a0a1, a2a3, a4a5 } + // (iii) Each thread j computes N[i][j]*P[j]= + // {{a0,a0a1},{a0a1a2,a0a1a2a3},{a0a1a2a3a4,a0a1a2a3a4a5},{a0a1a2a3a4a5a6,a0a1a2a3a4a5a6a7}} + std::vector partial_numerators(num_threads); + std::vector partial_denominators(num_threads); + + parallel_for(num_threads, [&](size_t thread_idx) { + const size_t start = idx_bounds[thread_idx].first; + const size_t end = idx_bounds[thread_idx].second; + for (size_t i = start; i < end - 1; ++i) { + if (check_is_active(i + 1)) { + // info("active"); + numerator.at(i + 1) *= numerator[i]; + denominator.at(i + 1) *= denominator[i]; + } else { + // info("inactive"); + numerator.at(i + 1) = numerator[i]; + denominator.at(i + 1) = denominator[i]; + } + // info("i = ", i, ", num = ", numerator.at(i)); + } + partial_numerators[thread_idx] = numerator[end - 1]; + partial_denominators[thread_idx] = denominator[end - 1]; + }); + + DEBUG_LOG_ALL(partial_numerators); + DEBUG_LOG_ALL(partial_denominators); + + parallel_for(num_threads, [&](size_t thread_idx) { + const size_t start = idx_bounds[thread_idx].first; + const size_t end = idx_bounds[thread_idx].second; + if (thread_idx > 0) { + FF numerator_scaling = 1; + FF denominator_scaling = 1; + + for (size_t j = 0; j < thread_idx; ++j) { + numerator_scaling *= partial_numerators[j]; + denominator_scaling *= partial_denominators[j]; + } + for (size_t i = start; i < end; ++i) { + numerator.at(i) = numerator[i] * numerator_scaling; + denominator.at(i) = denominator[i] * denominator_scaling; + // info("i = ", i, ", numer = ", numerator.at(i)); + } + } + + // Final step: invert denominator + FF::batch_invert(std::span{ &denominator.data()[start], end - start }); + }); + + DEBUG_LOG_ALL(numerator.coeffs()); + DEBUG_LOG_ALL(denominator.coeffs()); + + // Step (3) Compute z_perm[i] = numerator[i] / denominator[i] + auto& grand_product_polynomial = GrandProdRelation::get_grand_product_polynomial(full_polynomials); + // We have a 'virtual' 0 at the start (as this is a to-be-shifted polynomial) + ASSERT(grand_product_polynomial.start_index() == 1); + + parallel_for(num_threads, [&](size_t thread_idx) { + const size_t start = idx_bounds[thread_idx].first; + const size_t end = idx_bounds[thread_idx].second; + for (size_t i = end; i-- > start;) { + if (check_is_active(i + 1)) { + grand_product_polynomial.at(i + 1) = numerator[i] * denominator[i]; + } else { + // Set the value in the inactive regions to the first active value in the active region that follows + for (size_t j = 0; j < active_block_ranges.size() - 1; ++j) { + auto& ranges = active_block_ranges; + // info("i + 1 = ", i + 1); + // info("ranges[j].second = ", ranges[j].second); + // info("ranges[j + 1].first = ", ranges[j + 1].first); + if (i + 1 >= ranges[j].second && i + 1 < ranges[j + 1].first) { + size_t val_idx = ranges[j + 1].first - 1; + // info("inactive value idx = ", val_idx); + grand_product_polynomial.at(i + 1) = numerator[val_idx] * denominator[val_idx]; + break; + } + } + } + // info("idx = ", i + 1, ", z_perm = ", grand_product_polynomial[i + 1]); + } + }); + + DEBUG_LOG_ALL(grand_product_polynomial.coeffs()); +} + /** * @brief Compute the grand product corresponding to each grand-product relation defined in the Flavor * diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp index 33e96c1a161..f0c825d4e7b 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp @@ -121,11 +121,20 @@ TYPED_TEST(MegaHonkTests, BasicStructured) // Construct and verify Honk proof using a structured trace TraceSettings trace_settings{ SMALL_TEST_STRUCTURE }; + // TraceSettings trace_settings{ MICRO_TEST_STRUCTURE }; auto proving_key = std::make_shared>(builder, trace_settings); Prover prover(proving_key); auto verification_key = std::make_shared(proving_key->proving_key); Verifier verifier(verification_key); auto proof = prover.construct_proof(); + + RelationChecker::check_all(proving_key->proving_key.polynomials, proving_key->relation_parameters); + + // for (size_t i = 0; i < proving_key->proving_key.circuit_size; ++i) { + // info("i = ", i, ", z_perm = ", proving_key->proving_key.polynomials.z_perm[i]); + // info("i = ", i, ", sigma_1 = ", proving_key->proving_key.polynomials.sigma_1[i]); + // } + EXPECT_TRUE(verifier.verify_proof(proof)); } @@ -169,6 +178,15 @@ TYPED_TEST(MegaHonkTests, DynamicVirtualSizeIncrease) Verifier verifier(verification_key); auto proof = prover.construct_proof(); + bool z_perm_nonzero = false; + for (size_t i = 0; i < circuit_size; ++i) { + if (proving_key->proving_key.polynomials.z_perm[i] != 0) { + z_perm_nonzero = true; + break; + } + } + EXPECT_TRUE(z_perm_nonzero); + RelationChecker::check_all(proving_key->proving_key.polynomials, proving_key->relation_parameters); EXPECT_TRUE(verifier.verify_proof(proof)); From deb1d65baa2cdceaf07302080e21dbd9b9d80d0f Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Thu, 2 Jan 2025 22:35:42 +0000 Subject: [PATCH 10/24] remove debug code for ci --- .../src/barretenberg/client_ivc/mock_circuit_producer.hpp | 8 ++++---- .../cpp/src/barretenberg/goblin/mock_circuits.hpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/mock_circuit_producer.hpp b/barretenberg/cpp/src/barretenberg/client_ivc/mock_circuit_producer.hpp index 6d7e7910fd4..fd252e713a9 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/mock_circuit_producer.hpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/mock_circuit_producer.hpp @@ -119,10 +119,10 @@ class PrivateFunctionExecutionMockCircuitProducer { mock_databus.populate_kernel_databus(circuit); // populate databus inputs/outputs ivc.complete_kernel_circuit_logic(circuit); // complete with recursive verifiers etc } else { - [[maybe_unused]] bool use_large_circuit = - large_first_app && (circuit_counter == 1); // first circuit is size 2^19 - GoblinMockCircuits::construct_mock_app_circuit(circuit, false); // construct mock app - mock_databus.populate_app_databus(circuit); // populate databus outputs + bool use_large_circuit = large_first_app && (circuit_counter == 1); // first circuit is size 2^19 + GoblinMockCircuits::construct_mock_app_circuit(circuit, use_large_circuit); // construct mock app + // GoblinMockCircuits::construct_mock_app_circuit(circuit, false); // construct mock app + mock_databus.populate_app_databus(circuit); // populate databus outputs } return circuit; } diff --git a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp index 11b11bd64b0..cfa0be29d3a 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp @@ -191,7 +191,7 @@ class GoblinMockCircuits { { PROFILE_THIS(); // DEBUG - // add_some_ecc_op_gates(builder); + add_some_ecc_op_gates(builder); MockCircuits::construct_arithmetic_circuit(builder); } From 339a5c9adb7e1a698600d7b9ec3bf8a65a9a03c0 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Fri, 3 Jan 2025 04:02:52 +0000 Subject: [PATCH 11/24] optimized version seems to be working, cleanup needed --- .../client_ivc/mock_circuit_producer.hpp | 9 +- .../src/barretenberg/goblin/mock_circuits.hpp | 2 +- .../library/grand_product_library.hpp | 169 +++++++++--------- .../stdlib_circuit_builders/mega_flavor.hpp | 19 ++ .../stdlib_circuit_builders/ultra_flavor.hpp | 19 ++ .../ultra_honk/mega_honk.test.cpp | 4 +- 6 files changed, 132 insertions(+), 90 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/mock_circuit_producer.hpp b/barretenberg/cpp/src/barretenberg/client_ivc/mock_circuit_producer.hpp index fd252e713a9..6a879c2e2c3 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/mock_circuit_producer.hpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/mock_circuit_producer.hpp @@ -119,10 +119,11 @@ class PrivateFunctionExecutionMockCircuitProducer { mock_databus.populate_kernel_databus(circuit); // populate databus inputs/outputs ivc.complete_kernel_circuit_logic(circuit); // complete with recursive verifiers etc } else { - bool use_large_circuit = large_first_app && (circuit_counter == 1); // first circuit is size 2^19 - GoblinMockCircuits::construct_mock_app_circuit(circuit, use_large_circuit); // construct mock app - // GoblinMockCircuits::construct_mock_app_circuit(circuit, false); // construct mock app - mock_databus.populate_app_databus(circuit); // populate databus outputs + [[maybe_unused]] bool use_large_circuit = + large_first_app && (circuit_counter == 1); // first circuit is size 2^19 + // GoblinMockCircuits::construct_mock_app_circuit(circuit, use_large_circuit); // construct mock app + GoblinMockCircuits::construct_mock_app_circuit(circuit, false); // construct mock app + mock_databus.populate_app_databus(circuit); // populate databus outputs } return circuit; } diff --git a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp index cfa0be29d3a..11b11bd64b0 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp @@ -191,7 +191,7 @@ class GoblinMockCircuits { { PROFILE_THIS(); // DEBUG - add_some_ecc_op_gates(builder); + // add_some_ecc_op_gates(builder); MockCircuits::construct_arithmetic_circuit(builder); } diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp index 655975e0af7..4cdd4b80557 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp @@ -3,6 +3,7 @@ #include "barretenberg/common/debug_log.hpp" #include "barretenberg/common/thread.hpp" #include "barretenberg/common/zip_view.hpp" +#include "barretenberg/flavor/flavor.hpp" #include "barretenberg/plonk/proof_system/proving_key/proving_key.hpp" #include "barretenberg/relations/relation_parameters.hpp" #include @@ -54,10 +55,10 @@ namespace bb { * @param size_override optional size of the domain; otherwise based on dyadic polynomial domain */ template -void compute_grand_product_old(typename Flavor::ProverPolynomials& full_polynomials, - bb::RelationParameters& relation_parameters, - size_t size_override = 0, - std::vector> active_block_ranges = {}) +void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, + bb::RelationParameters& relation_parameters, + size_t size_override = 0, + std::vector> active_block_ranges = {}) { PROFILE_THIS_NAME("compute_grand_product"); @@ -81,12 +82,13 @@ void compute_grand_product_old(typename Flavor::ProverPolynomials& full_polynomi } } } + size_t active_domain_size = active_idxs.size(); // const size_t num_threads = 4; std::vector> idx_bounds; const size_t num_threads = calculate_num_threads(domain_size, /*min_iterations_per_thread=*/1 << 14); { - info("num_threads = ", num_threads); + // info("num_threads = ", num_threads); // const size_t num_threads = domain_size >= get_num_cpus_pow2() ? get_num_cpus_pow2() : 1; const size_t block_size = domain_size / num_threads; const size_t final_idx = domain_size - 1; @@ -97,8 +99,8 @@ void compute_grand_product_old(typename Flavor::ProverPolynomials& full_polynomi const size_t start = thread_idx * block_size; const size_t end = (thread_idx == num_threads - 1) ? final_idx : (thread_idx + 1) * block_size; idx_bounds.push_back(std::make_pair(start, end)); - info("idx_bounds.start = ", start); - info("idx_bounds.end = ", end); + // info("idx_bounds.start = ", start); + // info("idx_bounds.end = ", end); } } @@ -120,11 +122,6 @@ void compute_grand_product_old(typename Flavor::ProverPolynomials& full_polynomi } } - // Allocate numerator/denominator polynomials that will serve as scratch space - // TODO(zac) we can re-use the permutation polynomial as the numerator polynomial. Reduces readability - Polynomial numerator{ domain_size, domain_size }; - Polynomial denominator{ domain_size, domain_size }; - auto check_is_active = [&](size_t idx) { if (active_block_ranges.empty()) { return true; @@ -134,54 +131,42 @@ void compute_grand_product_old(typename Flavor::ProverPolynomials& full_polynomi }); }; - for (auto range : active_block_ranges) { - info("start = ", range.first); - info("end = ", range.second); - } + // Allocate numerator/denominator polynomials that will serve as scratch space + // TODO(zac) we can re-use the permutation polynomial as the numerator polynomial. Reduces readability + Polynomial numerator{ active_domain_size }; + Polynomial denominator{ active_domain_size }; + + // for (auto range : active_block_ranges) { + // info("start = ", range.first); + // info("end = ", range.second); + // } // Step (1) // Populate `numerator` and `denominator` with the algebra described by Relation { PROFILE_THIS_NAME("GP step 1"); - parallel_for(num_threads, [&](size_t thread_idx) { + parallel_for(active_num_threads, [&](size_t thread_idx) { typename Flavor::AllValues row; - const size_t start = idx_bounds[thread_idx].first; - const size_t end = idx_bounds[thread_idx].second; + const size_t start = active_idx_bounds[thread_idx].first; + const size_t end = active_idx_bounds[thread_idx].second; for (size_t i = start; i < end; ++i) { - if (check_is_active(i)) { - // TODO(https://github.com/AztecProtocol/barretenberg/issues/940):consider avoiding get_row if - // possible. - row = full_polynomials.get_row(i); - numerator.at(i) = GrandProdRelation::template compute_grand_product_numerator( - row, relation_parameters); - denominator.at(i) = GrandProdRelation::template compute_grand_product_denominator( - row, relation_parameters); + // TODO(https://github.com/AztecProtocol/barretenberg/issues/940):consider avoiding get_row if + // possible. + auto poly_idx = active_idxs[i]; + if constexpr (IsUltraFlavor) { + + row = full_polynomials.get_row_for_perm(poly_idx); } else { - numerator.at(i) = 1; - denominator.at(i) = 1; + row = full_polynomials.get_row(poly_idx); } - info("num = ", numerator.at(i)); - info("den = ", denominator.at(i)); + numerator.at(i) = + GrandProdRelation::template compute_grand_product_numerator(row, relation_parameters); + denominator.at(i) = GrandProdRelation::template compute_grand_product_denominator( + row, relation_parameters); + + // info("poly_idx = ", poly_idx, ", num = ", numerator.at(i)); } }); - // parallel_for(active_num_threads, [&](size_t thread_idx) { - // typename Flavor::AllValues row; - // const size_t start = active_idx_bounds[thread_idx].first; - // const size_t end = active_idx_bounds[thread_idx].second; - // for (size_t i = start; i < end; ++i) { - // // TODO(https://github.com/AztecProtocol/barretenberg/issues/940):consider avoiding get_row if - // // possible. - // size_t idx = active_idxs[i]; - // row = full_polynomials.get_row(idx); // WORKTODO: implement get_row_for_permuation_argument? - // numerator.at(idx) = - // GrandProdRelation::template compute_grand_product_numerator(row, - // relation_parameters); - // denominator.at(idx) = GrandProdRelation::template compute_grand_product_denominator( - // row, relation_parameters); - // info("num = ", numerator.at(idx)); - // info("den = ", denominator.at(idx)); - // } - // }); } DEBUG_LOG_ALL(numerator.coeffs()); @@ -199,22 +184,19 @@ void compute_grand_product_old(typename Flavor::ProverPolynomials& full_polynomi // (ii) Take partial products P = { 1, a0a1, a2a3, a4a5 } // (iii) Each thread j computes N[i][j]*P[j]= // {{a0,a0a1},{a0a1a2,a0a1a2a3},{a0a1a2a3a4,a0a1a2a3a4a5},{a0a1a2a3a4a5a6,a0a1a2a3a4a5a6a7}} - std::vector partial_numerators(num_threads); - std::vector partial_denominators(num_threads); + std::vector partial_numerators(active_num_threads); + std::vector partial_denominators(active_num_threads); { - info("GP step 2.1"); + // info("GP step 2.1"); PROFILE_THIS_NAME("GP step 2.1"); - parallel_for(num_threads, [&](size_t thread_idx) { - const size_t start = idx_bounds[thread_idx].first; - const size_t end = idx_bounds[thread_idx].second; + parallel_for(active_num_threads, [&](size_t thread_idx) { + const size_t start = active_idx_bounds[thread_idx].first; + const size_t end = active_idx_bounds[thread_idx].second; for (size_t i = start; i < end - 1; ++i) { - if (check_is_active(i + 1)) { - numerator.at(i + 1) *= numerator[i]; - denominator.at(i + 1) *= denominator[i]; - } - info("num = ", numerator.at(i + 1)); - info("den = ", denominator.at(i + 1)); + numerator.at(i + 1) *= numerator[i]; + denominator.at(i + 1) *= denominator[i]; + // info("poly_idx = ", active_idxs[i], ", numer = ", numerator.at(i)); } partial_numerators[thread_idx] = numerator[end - 1]; partial_denominators[thread_idx] = denominator[end - 1]; @@ -225,9 +207,9 @@ void compute_grand_product_old(typename Flavor::ProverPolynomials& full_polynomi } { PROFILE_THIS_NAME("GP step 2.2"); - parallel_for(num_threads, [&](size_t thread_idx) { - const size_t start = idx_bounds[thread_idx].first; - const size_t end = idx_bounds[thread_idx].second; + parallel_for(active_num_threads, [&](size_t thread_idx) { + const size_t start = active_idx_bounds[thread_idx].first; + const size_t end = active_idx_bounds[thread_idx].second; if (thread_idx > 0) { FF numerator_scaling = 1; FF denominator_scaling = 1; @@ -259,38 +241,57 @@ void compute_grand_product_old(typename Flavor::ProverPolynomials& full_polynomi { PROFILE_THIS_NAME("GP step 3"); + parallel_for(active_num_threads, [&](size_t thread_idx) { + const size_t start = active_idx_bounds[thread_idx].first; + const size_t end = active_idx_bounds[thread_idx].second; + for (size_t i = start; i < end; ++i) { + auto poly_idx = active_idxs[i + 1]; + grand_product_polynomial.at(poly_idx) = numerator[i] * denominator[i]; + + // info("poly_idx = ", poly_idx, ", z_perm = ", grand_product_polynomial[poly_idx]); + // info("active = ", check_is_active(i + 1)); + // info("GP(", i + 1, ") = ", grand_product_polynomial.at(i + 1)); + } + }); + } + + { + PROFILE_THIS_NAME("GP step 4"); parallel_for(num_threads, [&](size_t thread_idx) { const size_t start = idx_bounds[thread_idx].first; const size_t end = idx_bounds[thread_idx].second; - for (size_t i = end; i-- > start;) { - // if (check_is_active(i + 1)) { - if (check_is_active(i)) { - grand_product_polynomial.at(i + 1) = numerator[i] * denominator[i]; - } else { - // Set the value in the inactive regions to the first active value in the active region that follows + for (size_t i = start; i < end; ++i) { + if (!check_is_active(i + 1)) { + // Set the value in the inactive regions to the first active value in the active region that + // follows for (size_t j = 0; j < active_block_ranges.size() - 1; ++j) { auto& ranges = active_block_ranges; + // info("i + 1 = ", i + 1); + // info("ranges[j].second = ", ranges[j].second); + // info("ranges[j + 1].first = ", ranges[j + 1].first); if (i + 1 >= ranges[j].second && i + 1 < ranges[j + 1].first) { size_t val_idx = ranges[j + 1].first; - grand_product_polynomial.at(i + 1) = numerator[val_idx] * denominator[val_idx]; + // info("inactive value idx = ", val_idx); + grand_product_polynomial.at(i + 1) = grand_product_polynomial[val_idx]; break; } } } - // info("active = ", check_is_active(i + 1)); - // info("GP(", i + 1, ") = ", grand_product_polynomial.at(i + 1)); + // info("idx = ", i + 1, ", z_perm = ", grand_product_polynomial[i + 1]); } }); + + grand_product_polynomial.at(1) = 1; } DEBUG_LOG_ALL(grand_product_polynomial.coeffs()); } template -void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, - bb::RelationParameters& relation_parameters, - size_t size_override = 0, - std::vector> active_block_ranges = {}) +void compute_grand_product_stable(typename Flavor::ProverPolynomials& full_polynomials, + bb::RelationParameters& relation_parameters, + size_t size_override = 0, + std::vector> active_block_ranges = {}) { PROFILE_THIS_NAME("compute_grand_product"); @@ -303,8 +304,8 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, using Polynomial = typename Flavor::Polynomial; using Accumulator = std::tuple_element_t<0, typename GrandProdRelation::SumcheckArrayOfValuesOverSubrelations>; - // Set the domain over which the grand product must be computed. This may be less than the dyadic circuit size, e.g - // the permutation grand product does not need to be computed beyond the index of the last active wire + // Set the domain over which the grand product must be computed. This may be less than the dyadic circuit size, + // e.g the permutation grand product does not need to be computed beyond the index of the last active wire size_t domain_size = size_override == 0 ? full_polynomials.get_polynomial_size() : size_override; const size_t num_threads = domain_size >= get_num_cpus_pow2() ? get_num_cpus_pow2() : 1; @@ -343,7 +344,8 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, const size_t end = idx_bounds[thread_idx].second; for (size_t i = start; i < end; ++i) { if (check_is_active(i)) { - // TODO(https://github.com/AztecProtocol/barretenberg/issues/940):consider avoiding get_row if possible. + // TODO(https://github.com/AztecProtocol/barretenberg/issues/940):consider avoiding get_row if + // possible. row = full_polynomials.get_row(i); numerator.at(i) = GrandProdRelation::template compute_grand_product_numerator(row, relation_parameters); @@ -353,6 +355,7 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, numerator.at(i) = 1; denominator.at(i) = 1; } + info("i = ", i, ", num = ", numerator.at(i)); } }); @@ -387,7 +390,7 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, numerator.at(i + 1) = numerator[i]; denominator.at(i + 1) = denominator[i]; } - // info("i = ", i, ", num = ", numerator.at(i)); + info("i = ", i, ", numer = ", numerator.at(i)); } partial_numerators[thread_idx] = numerator[end - 1]; partial_denominators[thread_idx] = denominator[end - 1]; @@ -410,7 +413,7 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, for (size_t i = start; i < end; ++i) { numerator.at(i) = numerator[i] * numerator_scaling; denominator.at(i) = denominator[i] * denominator_scaling; - // info("i = ", i, ", numer = ", numerator.at(i)); + info("i = ", i, ", numerator = ", numerator.at(i)); } } @@ -447,7 +450,7 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, } } } - // info("idx = ", i + 1, ", z_perm = ", grand_product_polynomial[i + 1]); + info("idx = ", i + 1, ", z_perm = ", grand_product_polynomial[i + 1]); } }); diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_flavor.hpp index 062929736f9..627293471e5 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_flavor.hpp @@ -383,6 +383,25 @@ class MegaFlavor { return result; } + [[nodiscard]] AllValues get_row_for_perm(size_t row_idx) const + { + PROFILE_THIS_NAME("MegaFlavor::get_row"); + AllValues result; + result.sigma_1 = this->sigma_1[row_idx]; + result.sigma_2 = this->sigma_2[row_idx]; + result.sigma_3 = this->sigma_3[row_idx]; + result.sigma_4 = this->sigma_4[row_idx]; + result.id_1 = this->id_1[row_idx]; + result.id_2 = this->id_2[row_idx]; + result.id_3 = this->id_3[row_idx]; + result.id_4 = this->id_4[row_idx]; + result.w_l = this->w_l[row_idx]; + result.w_r = this->w_r[row_idx]; + result.w_o = this->w_o[row_idx]; + result.w_4 = this->w_4[row_idx]; + return result; + } + void set_shifted() { for (auto [shifted, to_be_shifted] : zip_view(get_shifted(), get_to_be_shifted())) { diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_flavor.hpp index 62bc329ba6d..4ba200b2697 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_flavor.hpp @@ -295,6 +295,25 @@ class UltraFlavor { return result; } + [[nodiscard]] AllValues get_row_for_perm(size_t row_idx) const + { + PROFILE_THIS_NAME("MegaFlavor::get_row"); + AllValues result; + result.sigma_1 = this->sigma_1[row_idx]; + result.sigma_2 = this->sigma_2[row_idx]; + result.sigma_3 = this->sigma_3[row_idx]; + result.sigma_4 = this->sigma_4[row_idx]; + result.id_1 = this->id_1[row_idx]; + result.id_2 = this->id_2[row_idx]; + result.id_3 = this->id_3[row_idx]; + result.id_4 = this->id_4[row_idx]; + result.w_l = this->w_l[row_idx]; + result.w_r = this->w_r[row_idx]; + result.w_o = this->w_o[row_idx]; + result.w_4 = this->w_4[row_idx]; + return result; + } + // Set all shifted polynomials based on their to-be-shifted counterpart void set_shifted() { diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp index f0c825d4e7b..c9383dd6eae 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp @@ -120,8 +120,8 @@ TYPED_TEST(MegaHonkTests, BasicStructured) GoblinMockCircuits::construct_simple_circuit(builder); // Construct and verify Honk proof using a structured trace - TraceSettings trace_settings{ SMALL_TEST_STRUCTURE }; - // TraceSettings trace_settings{ MICRO_TEST_STRUCTURE }; + // TraceSettings trace_settings{ SMALL_TEST_STRUCTURE }; + TraceSettings trace_settings{ MICRO_TEST_STRUCTURE }; auto proving_key = std::make_shared>(builder, trace_settings); Prover prover(proving_key); auto verification_key = std::make_shared(proving_key->proving_key); From 5471504144d4fb520c07fd257dd91952116d2775 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Fri, 3 Jan 2025 16:41:13 +0000 Subject: [PATCH 12/24] some fixes, see what fails --- .../client_ivc/mock_circuit_producer.hpp | 9 +++++---- barretenberg/cpp/src/barretenberg/constants.hpp | 1 + .../cpp/src/barretenberg/goblin/mock_circuits.hpp | 2 +- .../library/grand_product_library.hpp | 13 +++++-------- .../src/barretenberg/ultra_honk/mega_honk.test.cpp | 4 ++-- 5 files changed, 14 insertions(+), 15 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/mock_circuit_producer.hpp b/barretenberg/cpp/src/barretenberg/client_ivc/mock_circuit_producer.hpp index 6a879c2e2c3..bfbddf6c2b2 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/mock_circuit_producer.hpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/mock_circuit_producer.hpp @@ -120,10 +120,11 @@ class PrivateFunctionExecutionMockCircuitProducer { ivc.complete_kernel_circuit_logic(circuit); // complete with recursive verifiers etc } else { [[maybe_unused]] bool use_large_circuit = - large_first_app && (circuit_counter == 1); // first circuit is size 2^19 - // GoblinMockCircuits::construct_mock_app_circuit(circuit, use_large_circuit); // construct mock app - GoblinMockCircuits::construct_mock_app_circuit(circuit, false); // construct mock app - mock_databus.populate_app_databus(circuit); // populate databus outputs + large_first_app && (circuit_counter == 1); // first circuit is size 2^19 + GoblinMockCircuits::construct_mock_app_circuit(circuit, use_large_circuit); // construct mock app + // DEBUG + // GoblinMockCircuits::construct_mock_app_circuit(circuit, false); // construct mock app + mock_databus.populate_app_databus(circuit); // populate databus outputs } return circuit; } diff --git a/barretenberg/cpp/src/barretenberg/constants.hpp b/barretenberg/cpp/src/barretenberg/constants.hpp index 4091be5e4dd..c8316fae31f 100644 --- a/barretenberg/cpp/src/barretenberg/constants.hpp +++ b/barretenberg/cpp/src/barretenberg/constants.hpp @@ -17,6 +17,7 @@ static constexpr uint32_t MAX_LOOKUP_TABLES_SIZE = 75000; static constexpr uint32_t MAX_DATABUS_SIZE = 10000; +// DEBUG // static constexpr uint32_t MAX_LOOKUP_TABLES_SIZE = 8; // static constexpr uint32_t MAX_DATABUS_SIZE = 2; diff --git a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp index 11b11bd64b0..cfa0be29d3a 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp @@ -191,7 +191,7 @@ class GoblinMockCircuits { { PROFILE_THIS(); // DEBUG - // add_some_ecc_op_gates(builder); + add_some_ecc_op_gates(builder); MockCircuits::construct_arithmetic_circuit(builder); } diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp index 4cdd4b80557..654d8a9969c 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp @@ -104,12 +104,11 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, } } - const size_t active_num_threads = calculate_num_threads(domain_size, /*min_iterations_per_thread=*/1 << 5); + const size_t active_num_threads = calculate_num_threads(active_domain_size, /*min_iterations_per_thread=*/1 << 3); std::vector> active_idx_bounds; { - size_t domain_size = active_idxs.size(); - const size_t block_size = domain_size / active_num_threads; - const size_t final_idx = domain_size - 1; + const size_t block_size = active_domain_size / active_num_threads; + const size_t final_idx = active_domain_size - 1; // Cumpute the index bounds for each thread for reuse in the computations below active_idx_bounds.reserve(active_num_threads); @@ -219,10 +218,8 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, denominator_scaling *= partial_denominators[j]; } for (size_t i = start; i < end; ++i) { - if (check_is_active(i)) { - numerator.at(i) = numerator[i] * numerator_scaling; - denominator.at(i) = denominator[i] * denominator_scaling; - } + numerator.at(i) = numerator[i] * numerator_scaling; + denominator.at(i) = denominator[i] * denominator_scaling; } } diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp index c9383dd6eae..f0c825d4e7b 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp @@ -120,8 +120,8 @@ TYPED_TEST(MegaHonkTests, BasicStructured) GoblinMockCircuits::construct_simple_circuit(builder); // Construct and verify Honk proof using a structured trace - // TraceSettings trace_settings{ SMALL_TEST_STRUCTURE }; - TraceSettings trace_settings{ MICRO_TEST_STRUCTURE }; + TraceSettings trace_settings{ SMALL_TEST_STRUCTURE }; + // TraceSettings trace_settings{ MICRO_TEST_STRUCTURE }; auto proving_key = std::make_shared>(builder, trace_settings); Prover prover(proving_key); auto verification_key = std::make_shared(proving_key->proving_key); From 4d7ea03b6197a5ab8ba0b5ed6c3f50181acdad68 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Fri, 3 Jan 2025 20:40:31 +0000 Subject: [PATCH 13/24] fix for client ivc --- .../library/grand_product_library.hpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp index 654d8a9969c..f8e17578128 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp @@ -278,7 +278,15 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, } }); - grand_product_polynomial.at(1) = 1; + // info("active_idxs[0] = ", active_idxs[0]); + // info("grand_product_polynomial.at(1) = ", grand_product_polynomial.at(1)); + // info("numerator[0] * denominator[0] = ", numerator[0] * denominator[0]); + // WORKTODO: getting rid of this makes the grand prod test pass but I think i needed it elsewhere.. + if (active_idxs[0] == 1) { + grand_product_polynomial.at(1) = 1; + } else { + grand_product_polynomial.at(1) = numerator[0] * denominator[0]; + } } DEBUG_LOG_ALL(grand_product_polynomial.coeffs()); From 7f348aaf4c11605037db74d66e336d2d2de1992f Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Fri, 3 Jan 2025 22:40:05 +0000 Subject: [PATCH 14/24] correct ivc structure --- .../execution_trace/mega_execution_trace.hpp | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/execution_trace/mega_execution_trace.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/execution_trace/mega_execution_trace.hpp index 2216b0f3a7d..f541678b9dd 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/execution_trace/mega_execution_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/execution_trace/mega_execution_trace.hpp @@ -301,28 +301,28 @@ static constexpr TraceStructure SMALL_TEST_STRUCTURE{ .ecc_op = 1 << 14, // .poseidon2_external = 2500, // .poseidon2_internal = 14000, // .overflow = 0 }; -static constexpr TraceStructure CLIENT_IVC_BENCH_STRUCTURE{ .ecc_op = 1 << 11, - .busread = 1 << 8, - .lookup = 144000, - .pub_inputs = 1 << 8, - .arithmetic = 396000, - .delta_range = 180000, - .elliptic = 18000, - .aux = 272000, - .poseidon2_external = 5000, - .poseidon2_internal = 28000, - .overflow = 0 }; -// static constexpr TraceStructure CLIENT_IVC_BENCH_STRUCTURE{ .ecc_op = 1 << 10, -// .busread = 1 << 7, -// .lookup = 72000, -// .pub_inputs = 1 << 7, -// .arithmetic = 198000, -// .delta_range = 90000, -// .elliptic = 9000, -// .aux = 136000, -// .poseidon2_external = 2500, -// .poseidon2_internal = 14000, +// static constexpr TraceStructure CLIENT_IVC_BENCH_STRUCTURE{ .ecc_op = 1 << 11, +// .busread = 1 << 8, +// .lookup = 144000, +// .pub_inputs = 1 << 8, +// .arithmetic = 396000, +// .delta_range = 180000, +// .elliptic = 18000, +// .aux = 272000, +// .poseidon2_external = 5000, +// .poseidon2_internal = 28000, // .overflow = 0 }; +static constexpr TraceStructure CLIENT_IVC_BENCH_STRUCTURE{ .ecc_op = 1 << 10, + .busread = 1 << 7, + .lookup = 72000, + .pub_inputs = 1 << 7, + .arithmetic = 198000, + .delta_range = 90000, + .elliptic = 9000, + .aux = 136000, + .poseidon2_external = 2500, + .poseidon2_internal = 14000, + .overflow = 0 }; /** * @brief An example structuring of size 2^18. From 8911c2f370ed11fd96e9f3b0f0ccf97c17a581ea Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Mon, 6 Jan 2025 00:37:56 +0000 Subject: [PATCH 15/24] some cleanup --- .../client_ivc/mock_circuit_producer.hpp | 7 +- .../cpp/src/barretenberg/common/thread.cpp | 27 ++ .../cpp/src/barretenberg/common/thread.hpp | 18 + .../execution_trace/mega_execution_trace.hpp | 22 -- .../library/grand_product_library.hpp | 336 +++--------------- 5 files changed, 94 insertions(+), 316 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/mock_circuit_producer.hpp b/barretenberg/cpp/src/barretenberg/client_ivc/mock_circuit_producer.hpp index bfbddf6c2b2..b2ba3f3656d 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/mock_circuit_producer.hpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/mock_circuit_producer.hpp @@ -119,12 +119,9 @@ class PrivateFunctionExecutionMockCircuitProducer { mock_databus.populate_kernel_databus(circuit); // populate databus inputs/outputs ivc.complete_kernel_circuit_logic(circuit); // complete with recursive verifiers etc } else { - [[maybe_unused]] bool use_large_circuit = - large_first_app && (circuit_counter == 1); // first circuit is size 2^19 + bool use_large_circuit = large_first_app && (circuit_counter == 1); // first circuit is size 2^19 GoblinMockCircuits::construct_mock_app_circuit(circuit, use_large_circuit); // construct mock app - // DEBUG - // GoblinMockCircuits::construct_mock_app_circuit(circuit, false); // construct mock app - mock_databus.populate_app_databus(circuit); // populate databus outputs + mock_databus.populate_app_databus(circuit); // populate databus outputs } return circuit; } diff --git a/barretenberg/cpp/src/barretenberg/common/thread.cpp b/barretenberg/cpp/src/barretenberg/common/thread.cpp index 11fafc1c43a..6e621923d6c 100644 --- a/barretenberg/cpp/src/barretenberg/common/thread.cpp +++ b/barretenberg/cpp/src/barretenberg/common/thread.cpp @@ -170,6 +170,33 @@ void parallel_for_heuristic(size_t num_points, }); }; +/** + * @brief Calculates number of threads and index bounds for each thread + * @details Finds the number of cpus with calculate_num_threads() then divides domain evenly amongst threads + * + * @param num_iterations + * @param min_iterations_per_thread + * @return size_t + */ +MultithreadData calculate_thread_data(size_t num_iterations, size_t min_iterations_per_thread) +{ + size_t num_threads = calculate_num_threads(num_iterations, min_iterations_per_thread); + + const size_t thread_size = num_iterations / num_threads; + const size_t final_idx = num_iterations - 1; + + std::vector start(num_threads); + std::vector end(num_threads); + + // Cumpute the index bounds for each thread + for (size_t thread_idx = 0; thread_idx < num_threads; ++thread_idx) { + start[thread_idx] = thread_idx * thread_size; + end[thread_idx] = (thread_idx == num_threads - 1) ? final_idx : (thread_idx + 1) * thread_size; + } + + return MultithreadData{ num_threads, start, end }; +} + /** * @brief calculates number of threads to create based on minimum iterations per thread * @details Finds the number of cpus with get_num_cpus(), and calculates `desired_num_threads` diff --git a/barretenberg/cpp/src/barretenberg/common/thread.hpp b/barretenberg/cpp/src/barretenberg/common/thread.hpp index ebf0d037200..c97aab48462 100644 --- a/barretenberg/cpp/src/barretenberg/common/thread.hpp +++ b/barretenberg/cpp/src/barretenberg/common/thread.hpp @@ -88,6 +88,24 @@ std::vector parallel_for_heuristic(size_t num_points, const size_t DEFAULT_MIN_ITERS_PER_THREAD = 1 << 4; +struct MultithreadData { + size_t num_threads; + // index bounds for each thread + std::vector start; + std::vector end; +}; + +/** + * @brief Calculates number of threads and index bounds for each thread + * @details Finds the number of cpus with calculate_num_threads() then divides domain evenly amongst threads + * + * @param num_iterations + * @param min_iterations_per_thread + * @return size_t + */ +MultithreadData calculate_thread_data(size_t num_iterations, + size_t min_iterations_per_thread = DEFAULT_MIN_ITERS_PER_THREAD); + /** * @brief calculates number of threads to create based on minimum iterations per thread * @details Finds the number of cpus with get_num_cpus(), and calculates `desired_num_threads` diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/execution_trace/mega_execution_trace.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/execution_trace/mega_execution_trace.hpp index f541678b9dd..d5880a64b05 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/execution_trace/mega_execution_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/execution_trace/mega_execution_trace.hpp @@ -290,28 +290,6 @@ static constexpr TraceStructure SMALL_TEST_STRUCTURE{ .ecc_op = 1 << 14, * @brief A minimal structuring specifically tailored to the medium complexity transaction of the Client IVC * benchmark. */ -// static constexpr TraceStructure CLIENT_IVC_BENCH_STRUCTURE{ .ecc_op = 1 << 10, -// .busread = 1 << 6, -// .lookup = 36000, -// .pub_inputs = 1 << 6, -// .arithmetic = 84000, -// .delta_range = 45000, -// .elliptic = 9000, -// .aux = 68000, -// .poseidon2_external = 2500, -// .poseidon2_internal = 14000, -// .overflow = 0 }; -// static constexpr TraceStructure CLIENT_IVC_BENCH_STRUCTURE{ .ecc_op = 1 << 11, -// .busread = 1 << 8, -// .lookup = 144000, -// .pub_inputs = 1 << 8, -// .arithmetic = 396000, -// .delta_range = 180000, -// .elliptic = 18000, -// .aux = 272000, -// .poseidon2_external = 5000, -// .poseidon2_internal = 28000, -// .overflow = 0 }; static constexpr TraceStructure CLIENT_IVC_BENCH_STRUCTURE{ .ecc_op = 1 << 10, .busread = 1 << 7, .lookup = 72000, diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp index f8e17578128..5f7d0ce336e 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp @@ -84,42 +84,8 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, } size_t active_domain_size = active_idxs.size(); - // const size_t num_threads = 4; - std::vector> idx_bounds; - const size_t num_threads = calculate_num_threads(domain_size, /*min_iterations_per_thread=*/1 << 14); - { - // info("num_threads = ", num_threads); - // const size_t num_threads = domain_size >= get_num_cpus_pow2() ? get_num_cpus_pow2() : 1; - const size_t block_size = domain_size / num_threads; - const size_t final_idx = domain_size - 1; - - // Cumpute the index bounds for each thread for reuse in the computations below - idx_bounds.reserve(num_threads); - for (size_t thread_idx = 0; thread_idx < num_threads; ++thread_idx) { - const size_t start = thread_idx * block_size; - const size_t end = (thread_idx == num_threads - 1) ? final_idx : (thread_idx + 1) * block_size; - idx_bounds.push_back(std::make_pair(start, end)); - // info("idx_bounds.start = ", start); - // info("idx_bounds.end = ", end); - } - } - - const size_t active_num_threads = calculate_num_threads(active_domain_size, /*min_iterations_per_thread=*/1 << 3); - std::vector> active_idx_bounds; - { - const size_t block_size = active_domain_size / active_num_threads; - const size_t final_idx = active_domain_size - 1; - - // Cumpute the index bounds for each thread for reuse in the computations below - active_idx_bounds.reserve(active_num_threads); - for (size_t thread_idx = 0; thread_idx < active_num_threads; ++thread_idx) { - const size_t start = thread_idx * block_size; - const size_t end = (thread_idx == active_num_threads - 1) ? final_idx : (thread_idx + 1) * block_size; - active_idx_bounds.push_back(std::make_pair(start, end)); - // info("idx_bounds.start = ", start); - // info("idx_bounds.end = ", end); - } - } + MultithreadData full_domain_thread_data = calculate_thread_data(domain_size); + MultithreadData active_range_thread_data = calculate_thread_data(active_domain_size); auto check_is_active = [&](size_t idx) { if (active_block_ranges.empty()) { @@ -135,232 +101,25 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, Polynomial numerator{ active_domain_size }; Polynomial denominator{ active_domain_size }; - // for (auto range : active_block_ranges) { - // info("start = ", range.first); - // info("end = ", range.second); - // } - - // Step (1) - // Populate `numerator` and `denominator` with the algebra described by Relation - { - PROFILE_THIS_NAME("GP step 1"); - parallel_for(active_num_threads, [&](size_t thread_idx) { - typename Flavor::AllValues row; - const size_t start = active_idx_bounds[thread_idx].first; - const size_t end = active_idx_bounds[thread_idx].second; - for (size_t i = start; i < end; ++i) { - // TODO(https://github.com/AztecProtocol/barretenberg/issues/940):consider avoiding get_row if - // possible. - auto poly_idx = active_idxs[i]; - if constexpr (IsUltraFlavor) { - - row = full_polynomials.get_row_for_perm(poly_idx); - } else { - row = full_polynomials.get_row(poly_idx); - } - numerator.at(i) = - GrandProdRelation::template compute_grand_product_numerator(row, relation_parameters); - denominator.at(i) = GrandProdRelation::template compute_grand_product_denominator( - row, relation_parameters); - - // info("poly_idx = ", poly_idx, ", num = ", numerator.at(i)); - } - }); - } - - DEBUG_LOG_ALL(numerator.coeffs()); - DEBUG_LOG_ALL(denominator.coeffs()); - - // Step (2) - // Compute the accumulating product of the numerator and denominator terms. - // This step is split into three parts for efficient multithreading: - // (i) compute ∏ A(j), ∏ B(j) subproducts for each thread - // (ii) compute scaling factor required to convert each subproduct into a single running product - // (ii) combine subproducts into a single running product - // - // For example, consider 4 threads and a size-8 numerator { a0, a1, a2, a3, a4, a5, a6, a7 } - // (i) Each thread computes 1 element of N = {{ a0, a0a1 }, { a2, a2a3 }, { a4, a4a5 }, { a6, a6a7 }} - // (ii) Take partial products P = { 1, a0a1, a2a3, a4a5 } - // (iii) Each thread j computes N[i][j]*P[j]= - // {{a0,a0a1},{a0a1a2,a0a1a2a3},{a0a1a2a3a4,a0a1a2a3a4a5},{a0a1a2a3a4a5a6,a0a1a2a3a4a5a6a7}} - std::vector partial_numerators(active_num_threads); - std::vector partial_denominators(active_num_threads); - - { - // info("GP step 2.1"); - PROFILE_THIS_NAME("GP step 2.1"); - parallel_for(active_num_threads, [&](size_t thread_idx) { - const size_t start = active_idx_bounds[thread_idx].first; - const size_t end = active_idx_bounds[thread_idx].second; - for (size_t i = start; i < end - 1; ++i) { - numerator.at(i + 1) *= numerator[i]; - denominator.at(i + 1) *= denominator[i]; - // info("poly_idx = ", active_idxs[i], ", numer = ", numerator.at(i)); - } - partial_numerators[thread_idx] = numerator[end - 1]; - partial_denominators[thread_idx] = denominator[end - 1]; - }); - - DEBUG_LOG_ALL(partial_numerators); - DEBUG_LOG_ALL(partial_denominators); - } - { - PROFILE_THIS_NAME("GP step 2.2"); - parallel_for(active_num_threads, [&](size_t thread_idx) { - const size_t start = active_idx_bounds[thread_idx].first; - const size_t end = active_idx_bounds[thread_idx].second; - if (thread_idx > 0) { - FF numerator_scaling = 1; - FF denominator_scaling = 1; - - for (size_t j = 0; j < thread_idx; ++j) { - numerator_scaling *= partial_numerators[j]; - denominator_scaling *= partial_denominators[j]; - } - for (size_t i = start; i < end; ++i) { - numerator.at(i) = numerator[i] * numerator_scaling; - denominator.at(i) = denominator[i] * denominator_scaling; - } - } - - // Final step: invert denominator - FF::batch_invert(std::span{ &denominator.data()[start], end - start }); - }); - } - - DEBUG_LOG_ALL(numerator.coeffs()); - DEBUG_LOG_ALL(denominator.coeffs()); - - // Step (3) Compute z_perm[i] = numerator[i] / denominator[i] - auto& grand_product_polynomial = GrandProdRelation::get_grand_product_polynomial(full_polynomials); - // We have a 'virtual' 0 at the start (as this is a to-be-shifted polynomial) - ASSERT(grand_product_polynomial.start_index() == 1); - - { - PROFILE_THIS_NAME("GP step 3"); - parallel_for(active_num_threads, [&](size_t thread_idx) { - const size_t start = active_idx_bounds[thread_idx].first; - const size_t end = active_idx_bounds[thread_idx].second; - for (size_t i = start; i < end; ++i) { - auto poly_idx = active_idxs[i + 1]; - grand_product_polynomial.at(poly_idx) = numerator[i] * denominator[i]; - - // info("poly_idx = ", poly_idx, ", z_perm = ", grand_product_polynomial[poly_idx]); - // info("active = ", check_is_active(i + 1)); - // info("GP(", i + 1, ") = ", grand_product_polynomial.at(i + 1)); - } - }); - } - - { - PROFILE_THIS_NAME("GP step 4"); - parallel_for(num_threads, [&](size_t thread_idx) { - const size_t start = idx_bounds[thread_idx].first; - const size_t end = idx_bounds[thread_idx].second; - for (size_t i = start; i < end; ++i) { - if (!check_is_active(i + 1)) { - // Set the value in the inactive regions to the first active value in the active region that - // follows - for (size_t j = 0; j < active_block_ranges.size() - 1; ++j) { - auto& ranges = active_block_ranges; - // info("i + 1 = ", i + 1); - // info("ranges[j].second = ", ranges[j].second); - // info("ranges[j + 1].first = ", ranges[j + 1].first); - if (i + 1 >= ranges[j].second && i + 1 < ranges[j + 1].first) { - size_t val_idx = ranges[j + 1].first; - // info("inactive value idx = ", val_idx); - grand_product_polynomial.at(i + 1) = grand_product_polynomial[val_idx]; - break; - } - } - } - // info("idx = ", i + 1, ", z_perm = ", grand_product_polynomial[i + 1]); - } - }); - - // info("active_idxs[0] = ", active_idxs[0]); - // info("grand_product_polynomial.at(1) = ", grand_product_polynomial.at(1)); - // info("numerator[0] * denominator[0] = ", numerator[0] * denominator[0]); - // WORKTODO: getting rid of this makes the grand prod test pass but I think i needed it elsewhere.. - if (active_idxs[0] == 1) { - grand_product_polynomial.at(1) = 1; - } else { - grand_product_polynomial.at(1) = numerator[0] * denominator[0]; - } - } - - DEBUG_LOG_ALL(grand_product_polynomial.coeffs()); -} - -template -void compute_grand_product_stable(typename Flavor::ProverPolynomials& full_polynomials, - bb::RelationParameters& relation_parameters, - size_t size_override = 0, - std::vector> active_block_ranges = {}) -{ - PROFILE_THIS_NAME("compute_grand_product"); - - for (auto range : active_block_ranges) { - info("start = ", range.first); - info("end = ", range.second); - } - - using FF = typename Flavor::FF; - using Polynomial = typename Flavor::Polynomial; - using Accumulator = std::tuple_element_t<0, typename GrandProdRelation::SumcheckArrayOfValuesOverSubrelations>; - - // Set the domain over which the grand product must be computed. This may be less than the dyadic circuit size, - // e.g the permutation grand product does not need to be computed beyond the index of the last active wire - size_t domain_size = size_override == 0 ? full_polynomials.get_polynomial_size() : size_override; - - const size_t num_threads = domain_size >= get_num_cpus_pow2() ? get_num_cpus_pow2() : 1; - const size_t block_size = domain_size / num_threads; - const size_t final_idx = domain_size - 1; - - // Cumpute the index bounds for each thread for reuse in the computations below - std::vector> idx_bounds; - idx_bounds.reserve(num_threads); - for (size_t thread_idx = 0; thread_idx < num_threads; ++thread_idx) { - const size_t start = thread_idx * block_size; - const size_t end = (thread_idx == num_threads - 1) ? final_idx : (thread_idx + 1) * block_size; - idx_bounds.push_back(std::make_pair(start, end)); - } - - // Allocate numerator/denominator polynomials that will serve as scratch space - // TODO(zac) we can re-use the permutation polynomial as the numerator polynomial. Reduces readability - Polynomial numerator{ domain_size, domain_size }; - Polynomial denominator{ domain_size, domain_size }; - - auto check_is_active = [&](size_t idx) { - if (active_block_ranges.empty()) { - return true; - } - return std::any_of(active_block_ranges.begin(), active_block_ranges.end(), [idx](const auto& range) { - return idx >= range.first && idx < range.second; - }); - }; - // Step (1) // Populate `numerator` and `denominator` with the algebra described by Relation - // FF gamma_fourth = relation_parameters.gamma.pow(4); - parallel_for(num_threads, [&](size_t thread_idx) { + parallel_for(active_range_thread_data.num_threads, [&](size_t thread_idx) { typename Flavor::AllValues row; - const size_t start = idx_bounds[thread_idx].first; - const size_t end = idx_bounds[thread_idx].second; + const size_t start = active_range_thread_data.start[thread_idx]; + const size_t end = active_range_thread_data.end[thread_idx]; for (size_t i = start; i < end; ++i) { - if (check_is_active(i)) { - // TODO(https://github.com/AztecProtocol/barretenberg/issues/940):consider avoiding get_row if - // possible. - row = full_polynomials.get_row(i); - numerator.at(i) = - GrandProdRelation::template compute_grand_product_numerator(row, relation_parameters); - denominator.at(i) = GrandProdRelation::template compute_grand_product_denominator( - row, relation_parameters); + // TODO(https://github.com/AztecProtocol/barretenberg/issues/940):consider avoiding get_row if + // possible. + auto poly_idx = active_idxs[i]; + if constexpr (IsUltraFlavor) { + row = full_polynomials.get_row_for_perm(poly_idx); } else { - numerator.at(i) = 1; - denominator.at(i) = 1; + row = full_polynomials.get_row(poly_idx); } - info("i = ", i, ", num = ", numerator.at(i)); + numerator.at(i) = + GrandProdRelation::template compute_grand_product_numerator(row, relation_parameters); + denominator.at(i) = + GrandProdRelation::template compute_grand_product_denominator(row, relation_parameters); } }); @@ -379,23 +138,15 @@ void compute_grand_product_stable(typename Flavor::ProverPolynomials& full_polyn // (ii) Take partial products P = { 1, a0a1, a2a3, a4a5 } // (iii) Each thread j computes N[i][j]*P[j]= // {{a0,a0a1},{a0a1a2,a0a1a2a3},{a0a1a2a3a4,a0a1a2a3a4a5},{a0a1a2a3a4a5a6,a0a1a2a3a4a5a6a7}} - std::vector partial_numerators(num_threads); - std::vector partial_denominators(num_threads); + std::vector partial_numerators(active_range_thread_data.num_threads); + std::vector partial_denominators(active_range_thread_data.num_threads); - parallel_for(num_threads, [&](size_t thread_idx) { - const size_t start = idx_bounds[thread_idx].first; - const size_t end = idx_bounds[thread_idx].second; + parallel_for(active_range_thread_data.num_threads, [&](size_t thread_idx) { + const size_t start = active_range_thread_data.start[thread_idx]; + const size_t end = active_range_thread_data.end[thread_idx]; for (size_t i = start; i < end - 1; ++i) { - if (check_is_active(i + 1)) { - // info("active"); - numerator.at(i + 1) *= numerator[i]; - denominator.at(i + 1) *= denominator[i]; - } else { - // info("inactive"); - numerator.at(i + 1) = numerator[i]; - denominator.at(i + 1) = denominator[i]; - } - info("i = ", i, ", numer = ", numerator.at(i)); + numerator.at(i + 1) *= numerator[i]; + denominator.at(i + 1) *= denominator[i]; } partial_numerators[thread_idx] = numerator[end - 1]; partial_denominators[thread_idx] = denominator[end - 1]; @@ -404,9 +155,9 @@ void compute_grand_product_stable(typename Flavor::ProverPolynomials& full_polyn DEBUG_LOG_ALL(partial_numerators); DEBUG_LOG_ALL(partial_denominators); - parallel_for(num_threads, [&](size_t thread_idx) { - const size_t start = idx_bounds[thread_idx].first; - const size_t end = idx_bounds[thread_idx].second; + parallel_for(active_range_thread_data.num_threads, [&](size_t thread_idx) { + const size_t start = active_range_thread_data.start[thread_idx]; + const size_t end = active_range_thread_data.end[thread_idx]; if (thread_idx > 0) { FF numerator_scaling = 1; FF denominator_scaling = 1; @@ -418,7 +169,6 @@ void compute_grand_product_stable(typename Flavor::ProverPolynomials& full_polyn for (size_t i = start; i < end; ++i) { numerator.at(i) = numerator[i] * numerator_scaling; denominator.at(i) = denominator[i] * denominator_scaling; - info("i = ", i, ", numerator = ", numerator.at(i)); } } @@ -434,31 +184,39 @@ void compute_grand_product_stable(typename Flavor::ProverPolynomials& full_polyn // We have a 'virtual' 0 at the start (as this is a to-be-shifted polynomial) ASSERT(grand_product_polynomial.start_index() == 1); - parallel_for(num_threads, [&](size_t thread_idx) { - const size_t start = idx_bounds[thread_idx].first; - const size_t end = idx_bounds[thread_idx].second; - for (size_t i = end; i-- > start;) { - if (check_is_active(i + 1)) { - grand_product_polynomial.at(i + 1) = numerator[i] * denominator[i]; - } else { + parallel_for(active_range_thread_data.num_threads, [&](size_t thread_idx) { + const size_t start = active_range_thread_data.start[thread_idx]; + const size_t end = active_range_thread_data.end[thread_idx]; + for (size_t i = start; i < end; ++i) { + auto poly_idx = active_idxs[i + 1]; + grand_product_polynomial.at(poly_idx) = numerator[i] * denominator[i]; + } + }); + + parallel_for(full_domain_thread_data.num_threads, [&](size_t thread_idx) { + const size_t start = full_domain_thread_data.start[thread_idx]; + const size_t end = full_domain_thread_data.end[thread_idx]; + for (size_t i = start; i < end; ++i) { + if (!check_is_active(i + 1)) { // Set the value in the inactive regions to the first active value in the active region that follows for (size_t j = 0; j < active_block_ranges.size() - 1; ++j) { auto& ranges = active_block_ranges; - // info("i + 1 = ", i + 1); - // info("ranges[j].second = ", ranges[j].second); - // info("ranges[j + 1].first = ", ranges[j + 1].first); if (i + 1 >= ranges[j].second && i + 1 < ranges[j + 1].first) { - size_t val_idx = ranges[j + 1].first - 1; - // info("inactive value idx = ", val_idx); - grand_product_polynomial.at(i + 1) = numerator[val_idx] * denominator[val_idx]; + size_t val_idx = ranges[j + 1].first; + grand_product_polynomial.at(i + 1) = grand_product_polynomial[val_idx]; break; } } } - info("idx = ", i + 1, ", z_perm = ", grand_product_polynomial[i + 1]); } }); + if (active_idxs[0] == 1) { + grand_product_polynomial.at(1) = 1; + } else { + grand_product_polynomial.at(1) = numerator[0] * denominator[0]; + } + DEBUG_LOG_ALL(grand_product_polynomial.coeffs()); } From 46e378ceafb888e2ab61c1daae918c2ba8703462 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Mon, 6 Jan 2025 03:01:12 +0000 Subject: [PATCH 16/24] clean and regularize --- .../library/grand_product_library.hpp | 34 +++++++++---------- .../stdlib_circuit_builders/mega_flavor.hpp | 24 ++++++------- .../stdlib_circuit_builders/ultra_flavor.hpp | 24 ++++++------- 3 files changed, 36 insertions(+), 46 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp index 5f7d0ce336e..7f6069173a1 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp @@ -70,27 +70,23 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, // the permutation grand product does not need to be computed beyond the index of the last active wire size_t domain_size = size_override == 0 ? full_polynomials.get_polynomial_size() : size_override; - std::vector active_idxs; + // If no active ranges have been specified, define the whole domain as the single active range if (active_block_ranges.empty()) { - for (size_t i = 0; i < domain_size; ++i) { + active_block_ranges.emplace_back(0, domain_size); + } + + // Explicitly construct the indices of the active rows + std::vector active_idxs; + for (auto& range : active_block_ranges) { + for (size_t i = range.first; i < range.second; ++i) { active_idxs.push_back(i); } - } else { - for (auto& range : active_block_ranges) { - for (size_t i = range.first; i < range.second; ++i) { - active_idxs.push_back(i); - } - } } size_t active_domain_size = active_idxs.size(); - MultithreadData full_domain_thread_data = calculate_thread_data(domain_size); MultithreadData active_range_thread_data = calculate_thread_data(active_domain_size); auto check_is_active = [&](size_t idx) { - if (active_block_ranges.empty()) { - return true; - } return std::any_of(active_block_ranges.begin(), active_block_ranges.end(), [idx](const auto& range) { return idx >= range.first && idx < range.second; }); @@ -104,17 +100,16 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, // Step (1) // Populate `numerator` and `denominator` with the algebra described by Relation parallel_for(active_range_thread_data.num_threads, [&](size_t thread_idx) { - typename Flavor::AllValues row; const size_t start = active_range_thread_data.start[thread_idx]; const size_t end = active_range_thread_data.end[thread_idx]; + typename Flavor::AllValues row; for (size_t i = start; i < end; ++i) { - // TODO(https://github.com/AztecProtocol/barretenberg/issues/940):consider avoiding get_row if - // possible. - auto poly_idx = active_idxs[i]; + // TODO(https://github.com/AztecProtocol/barretenberg/issues/940):consider avoiding get_row if possible. + auto row_idx = active_idxs[i]; if constexpr (IsUltraFlavor) { - row = full_polynomials.get_row_for_perm(poly_idx); + row = full_polynomials.get_row_for_permutation_arg(row_idx); } else { - row = full_polynomials.get_row(poly_idx); + row = full_polynomials.get_row(row_idx); } numerator.at(i) = GrandProdRelation::template compute_grand_product_numerator(row, relation_parameters); @@ -193,6 +188,9 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, } }); + // Final step is to populate the constant values of the grand product in the inactive regions + MultithreadData full_domain_thread_data = calculate_thread_data(domain_size); + parallel_for(full_domain_thread_data.num_threads, [&](size_t thread_idx) { const size_t start = full_domain_thread_data.start[thread_idx]; const size_t end = full_domain_thread_data.end[thread_idx]; diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_flavor.hpp index 627293471e5..e3d025af820 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_flavor.hpp @@ -383,22 +383,18 @@ class MegaFlavor { return result; } - [[nodiscard]] AllValues get_row_for_perm(size_t row_idx) const + [[nodiscard]] AllValues get_row_for_permutation_arg(size_t row_idx) { - PROFILE_THIS_NAME("MegaFlavor::get_row"); AllValues result; - result.sigma_1 = this->sigma_1[row_idx]; - result.sigma_2 = this->sigma_2[row_idx]; - result.sigma_3 = this->sigma_3[row_idx]; - result.sigma_4 = this->sigma_4[row_idx]; - result.id_1 = this->id_1[row_idx]; - result.id_2 = this->id_2[row_idx]; - result.id_3 = this->id_3[row_idx]; - result.id_4 = this->id_4[row_idx]; - result.w_l = this->w_l[row_idx]; - result.w_r = this->w_r[row_idx]; - result.w_o = this->w_o[row_idx]; - result.w_4 = this->w_4[row_idx]; + for (auto [result_field, polynomial] : zip_view(result.get_sigma_polynomials(), get_sigma_polynomials())) { + result_field = polynomial[row_idx]; + } + for (auto [result_field, polynomial] : zip_view(result.get_id_polynomials(), get_id_polynomials())) { + result_field = polynomial[row_idx]; + } + for (auto [result_field, polynomial] : zip_view(result.get_wires(), get_wires())) { + result_field = polynomial[row_idx]; + } return result; } diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_flavor.hpp index 4ba200b2697..dad8f86bef5 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_flavor.hpp @@ -295,22 +295,18 @@ class UltraFlavor { return result; } - [[nodiscard]] AllValues get_row_for_perm(size_t row_idx) const + [[nodiscard]] AllValues get_row_for_permutation_arg(size_t row_idx) { - PROFILE_THIS_NAME("MegaFlavor::get_row"); AllValues result; - result.sigma_1 = this->sigma_1[row_idx]; - result.sigma_2 = this->sigma_2[row_idx]; - result.sigma_3 = this->sigma_3[row_idx]; - result.sigma_4 = this->sigma_4[row_idx]; - result.id_1 = this->id_1[row_idx]; - result.id_2 = this->id_2[row_idx]; - result.id_3 = this->id_3[row_idx]; - result.id_4 = this->id_4[row_idx]; - result.w_l = this->w_l[row_idx]; - result.w_r = this->w_r[row_idx]; - result.w_o = this->w_o[row_idx]; - result.w_4 = this->w_4[row_idx]; + for (auto [result_field, polynomial] : zip_view(result.get_sigma_polynomials(), get_sigma_polynomials())) { + result_field = polynomial[row_idx]; + } + for (auto [result_field, polynomial] : zip_view(result.get_id_polynomials(), get_id_polynomials())) { + result_field = polynomial[row_idx]; + } + for (auto [result_field, polynomial] : zip_view(result.get_wires(), get_wires())) { + result_field = polynomial[row_idx]; + } return result; } From d0ea21a5efbed2f998eaacb83208c62b9768bb77 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Mon, 6 Jan 2025 14:14:02 +0000 Subject: [PATCH 17/24] fix index error in thread method --- .../cpp/src/barretenberg/common/thread.cpp | 7 ++---- .../composer/permutation_lib.hpp | 11 +++++----- .../library/grand_product_library.hpp | 22 +++++++++++++------ 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/common/thread.cpp b/barretenberg/cpp/src/barretenberg/common/thread.cpp index 6e621923d6c..9e0a191eaa8 100644 --- a/barretenberg/cpp/src/barretenberg/common/thread.cpp +++ b/barretenberg/cpp/src/barretenberg/common/thread.cpp @@ -181,17 +181,14 @@ void parallel_for_heuristic(size_t num_points, MultithreadData calculate_thread_data(size_t num_iterations, size_t min_iterations_per_thread) { size_t num_threads = calculate_num_threads(num_iterations, min_iterations_per_thread); - const size_t thread_size = num_iterations / num_threads; - const size_t final_idx = num_iterations - 1; + // Cumpute the index bounds for each thread std::vector start(num_threads); std::vector end(num_threads); - - // Cumpute the index bounds for each thread for (size_t thread_idx = 0; thread_idx < num_threads; ++thread_idx) { start[thread_idx] = thread_idx * thread_size; - end[thread_idx] = (thread_idx == num_threads - 1) ? final_idx : (thread_idx + 1) * thread_size; + end[thread_idx] = (thread_idx == num_threads - 1) ? num_iterations : (thread_idx + 1) * thread_size; } return MultithreadData{ num_threads, start, end }; diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/composer/permutation_lib.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/composer/permutation_lib.hpp index 1ce196e69b4..d6e835059cb 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/composer/permutation_lib.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/composer/permutation_lib.hpp @@ -225,15 +225,14 @@ void compute_honk_style_permutation_lagrange_polynomials_from_mapping( const size_t num_gates = proving_key->circuit_size; size_t domain_size = proving_key->active_idxs.size(); - size_t num_threads = calculate_num_threads(domain_size, /*min_iterations_per_thread=*/1 << 5); - size_t thread_size = domain_size / num_threads; - size_t leftover = domain_size % num_threads; + + const MultithreadData thread_data = calculate_thread_data(domain_size, /*min_iterations_per_thread=*/1 << 5); size_t wire_idx = 0; for (auto& current_permutation_poly : permutation_polynomials) { - parallel_for(num_threads, [&](size_t j) { - const size_t start = j * thread_size; - const size_t end = (j == num_threads - 1) ? (j + 1) * thread_size + leftover : (j + 1) * thread_size; + parallel_for(thread_data.num_threads, [&](size_t j) { + const size_t start = thread_data.start[j]; + const size_t end = thread_data.end[j]; for (size_t i = start; i < end; ++i) { size_t poly_idx = proving_key->active_idxs[i]; auto idx = static_cast(poly_idx); diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp index 7f6069173a1..b82c7945a6d 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp @@ -82,9 +82,11 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, active_idxs.push_back(i); } } - size_t active_domain_size = active_idxs.size(); + // The size of the iteration domain is one less than the number of active rows since the final value of the grand + // product is constructed only in the relation and not explicitly in the polynomial + size_t active_domain_size = active_idxs.size() - 1; - MultithreadData active_range_thread_data = calculate_thread_data(active_domain_size); + const MultithreadData active_range_thread_data = calculate_thread_data(active_domain_size); auto check_is_active = [&](size_t idx) { return std::any_of(active_block_ranges.begin(), active_block_ranges.end(), [idx](const auto& range) { @@ -179,6 +181,10 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, // We have a 'virtual' 0 at the start (as this is a to-be-shifted polynomial) ASSERT(grand_product_polynomial.start_index() == 1); + if constexpr (IsUltraFlavor) { + grand_product_polynomial.at(1) = 1; + } + parallel_for(active_range_thread_data.num_threads, [&](size_t thread_idx) { const size_t start = active_range_thread_data.start[thread_idx]; const size_t end = active_range_thread_data.end[thread_idx]; @@ -191,6 +197,12 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, // Final step is to populate the constant values of the grand product in the inactive regions MultithreadData full_domain_thread_data = calculate_thread_data(domain_size); + // WORKTODO: I think the fundamental problem that leads to this wierd backwards setting of constant values based on + // the start of the next active region is that the indices in z_perm are offset from the indices of num/denom by 1. + // I.e. the values of num at i determine the values of z_perm at i+1. So I think we should really use the values in + // active region j to set values [start_j + 1, end_j) in z_perm. This would then mean setting the constant values in + // a dead region (up to and including the value in the next active region) to the value that immediately preceded it + // (at the first index of the dead region) parallel_for(full_domain_thread_data.num_threads, [&](size_t thread_idx) { const size_t start = full_domain_thread_data.start[thread_idx]; const size_t end = full_domain_thread_data.end[thread_idx]; @@ -209,11 +221,7 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, } }); - if (active_idxs[0] == 1) { - grand_product_polynomial.at(1) = 1; - } else { - grand_product_polynomial.at(1) = numerator[0] * denominator[0]; - } + info("grand_product_polynomial.at(1) = ", grand_product_polynomial.at(1)); DEBUG_LOG_ALL(grand_product_polynomial.coeffs()); } From 45156f7dc971c202341b731d048296c4f6716b45 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Mon, 6 Jan 2025 15:22:45 +0000 Subject: [PATCH 18/24] clarify and clean --- .../library/grand_product_library.hpp | 41 +++++++------------ 1 file changed, 15 insertions(+), 26 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp index b82c7945a6d..b5f4c9e942d 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp @@ -88,12 +88,6 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, const MultithreadData active_range_thread_data = calculate_thread_data(active_domain_size); - auto check_is_active = [&](size_t idx) { - return std::any_of(active_block_ranges.begin(), active_block_ranges.end(), [idx](const auto& range) { - return idx >= range.first && idx < range.second; - }); - }; - // Allocate numerator/denominator polynomials that will serve as scratch space // TODO(zac) we can re-use the permutation polynomial as the numerator polynomial. Reduces readability Polynomial numerator{ active_domain_size }; @@ -194,35 +188,30 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, } }); - // Final step is to populate the constant values of the grand product in the inactive regions + // Final step: The grand product is constant in the inactive regions of the trace (since there are no copy + // constraints there). These constant values have already been computed and are equal to the first value in the + // active region that follows MultithreadData full_domain_thread_data = calculate_thread_data(domain_size); - // WORKTODO: I think the fundamental problem that leads to this wierd backwards setting of constant values based on - // the start of the next active region is that the indices in z_perm are offset from the indices of num/denom by 1. - // I.e. the values of num at i determine the values of z_perm at i+1. So I think we should really use the values in - // active region j to set values [start_j + 1, end_j) in z_perm. This would then mean setting the constant values in - // a dead region (up to and including the value in the next active region) to the value that immediately preceded it - // (at the first index of the dead region) + // Lambda to set the constant inactive regions of the grand product if they exist + auto set_constant_value_if_inactive = [&](size_t i) { + for (size_t j = 0; j < active_block_ranges.size() - 1; ++j) { + if (i >= active_block_ranges[j].second && i < active_block_ranges[j + 1].first) { + size_t constant_value_idx = active_block_ranges[j + 1].first; + grand_product_polynomial.at(i) = grand_product_polynomial[constant_value_idx]; + break; + } + } + }; + parallel_for(full_domain_thread_data.num_threads, [&](size_t thread_idx) { const size_t start = full_domain_thread_data.start[thread_idx]; const size_t end = full_domain_thread_data.end[thread_idx]; for (size_t i = start; i < end; ++i) { - if (!check_is_active(i + 1)) { - // Set the value in the inactive regions to the first active value in the active region that follows - for (size_t j = 0; j < active_block_ranges.size() - 1; ++j) { - auto& ranges = active_block_ranges; - if (i + 1 >= ranges[j].second && i + 1 < ranges[j + 1].first) { - size_t val_idx = ranges[j + 1].first; - grand_product_polynomial.at(i + 1) = grand_product_polynomial[val_idx]; - break; - } - } - } + set_constant_value_if_inactive(i); } }); - info("grand_product_polynomial.at(1) = ", grand_product_polynomial.at(1)); - DEBUG_LOG_ALL(grand_product_polynomial.coeffs()); } From 0ebd6072fc33efb85e0fcd189d9c5b9563e3dd4a Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Mon, 6 Jan 2025 17:44:32 +0000 Subject: [PATCH 19/24] active regions model working --- .../cpp/src/barretenberg/common/thread.cpp | 8 -- .../cpp/src/barretenberg/flavor/flavor.hpp | 10 ++- .../composer/permutation_lib.hpp | 4 +- .../library/grand_product_library.hpp | 81 ++++++++++++------- .../protogalaxy/protogalaxy.test.cpp | 9 +-- .../protogalaxy_recursive_verifier.test.cpp | 9 +-- .../stdlib_circuit_builders/mega_flavor.hpp | 2 +- .../trace_to_polynomials.cpp | 4 +- .../barretenberg/ultra_honk/oink_prover.cpp | 12 +-- 9 files changed, 75 insertions(+), 64 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/common/thread.cpp b/barretenberg/cpp/src/barretenberg/common/thread.cpp index 9e0a191eaa8..2fdefc82f65 100644 --- a/barretenberg/cpp/src/barretenberg/common/thread.cpp +++ b/barretenberg/cpp/src/barretenberg/common/thread.cpp @@ -170,14 +170,6 @@ void parallel_for_heuristic(size_t num_points, }); }; -/** - * @brief Calculates number of threads and index bounds for each thread - * @details Finds the number of cpus with calculate_num_threads() then divides domain evenly amongst threads - * - * @param num_iterations - * @param min_iterations_per_thread - * @return size_t - */ MultithreadData calculate_thread_data(size_t num_iterations, size_t min_iterations_per_thread) { size_t num_threads = calculate_num_threads(num_iterations, min_iterations_per_thread); diff --git a/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp b/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp index 6b64495c09d..09b3a796f6b 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp @@ -98,6 +98,11 @@ class PrecomputedEntitiesBase { uint64_t log_circuit_size; uint64_t num_public_inputs; }; +// Specifies the regions of the execution trace containing non-trivial wire values +struct ActiveRegionData { + std::vector> ranges; // active ranges [start_i, end_i) of the execution trace + std::vector idxs; // full set of poly indices corresposponding to active ranges +}; /** * @brief Base proving key class. @@ -123,10 +128,7 @@ template class ProvingKey_ { // folded element by element. std::vector public_inputs; - // Ranges of the form [start, end) where witnesses have non-zero values (hence the execution trace is "active") - std::vector> active_block_ranges; - // The actual polynomial indices corresposponding to the active block ranges - std::vector active_idxs; + ActiveRegionData active_region_data; // specifies active regions of execution trace ProvingKey_() = default; ProvingKey_(const size_t dyadic_circuit_size, diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/composer/permutation_lib.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/composer/permutation_lib.hpp index d6e835059cb..3660eff0028 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/composer/permutation_lib.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/composer/permutation_lib.hpp @@ -224,7 +224,7 @@ void compute_honk_style_permutation_lagrange_polynomials_from_mapping( using FF = typename Flavor::FF; const size_t num_gates = proving_key->circuit_size; - size_t domain_size = proving_key->active_idxs.size(); + size_t domain_size = proving_key->active_region_data.idxs.size(); const MultithreadData thread_data = calculate_thread_data(domain_size, /*min_iterations_per_thread=*/1 << 5); @@ -234,7 +234,7 @@ void compute_honk_style_permutation_lagrange_polynomials_from_mapping( const size_t start = thread_data.start[j]; const size_t end = thread_data.end[j]; for (size_t i = start; i < end; ++i) { - size_t poly_idx = proving_key->active_idxs[i]; + size_t poly_idx = proving_key->active_region_data.idxs[i]; auto idx = static_cast(poly_idx); const auto& current_row_idx = permutation_mappings[wire_idx].row_idx[idx]; const auto& current_col_idx = permutation_mappings[wire_idx].col_idx[idx]; diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp index b5f4c9e942d..8ece3a1c371 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp @@ -6,6 +6,7 @@ #include "barretenberg/flavor/flavor.hpp" #include "barretenberg/plonk/proof_system/proving_key/proving_key.hpp" #include "barretenberg/relations/relation_parameters.hpp" +#include "barretenberg/trace_to_polynomials/trace_to_polynomials.hpp" #include namespace bb { @@ -58,7 +59,7 @@ template void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, bb::RelationParameters& relation_parameters, size_t size_override = 0, - std::vector> active_block_ranges = {}) + const ActiveRegionData& active_region_data = ActiveRegionData{}) { PROFILE_THIS_NAME("compute_grand_product"); @@ -70,21 +71,43 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, // the permutation grand product does not need to be computed beyond the index of the last active wire size_t domain_size = size_override == 0 ? full_polynomials.get_polynomial_size() : size_override; - // If no active ranges have been specified, define the whole domain as the single active range - if (active_block_ranges.empty()) { - active_block_ranges.emplace_back(0, domain_size); - } + // // If no active ranges have been specified, define the whole domain as the single active range + // if (active_region_data.ranges.empty()) { + // active_region_data.ranges.emplace_back(0, domain_size); + // } + + // auto execute_parallel_for_on_active_domain = [&](size_t num_iterations, const std::function& func) + // { + // MultithreadData thread_data; - // Explicitly construct the indices of the active rows - std::vector active_idxs; - for (auto& range : active_block_ranges) { - for (size_t i = range.first; i < range.second; ++i) { - active_idxs.push_back(i); + // if (active_region_data.ranges.empty()) { + // thread_data = calculate_thread_data(domain_size); + // parallel_for(thread_data.num_threads, func) {} + // else + // { + // } + // }; + // }; + + auto get_active_range_poly_idx = [&](size_t i) { + if (active_region_data.idxs.empty()) { + return i; } - } - // The size of the iteration domain is one less than the number of active rows since the final value of the grand - // product is constructed only in the relation and not explicitly in the polynomial - size_t active_domain_size = active_idxs.size() - 1; + return active_region_data.idxs[i]; + }; + + // // Explicitly construct the indices of the active rows + // std::vector active_region_data.idxs; + // for (auto& range : active_region_data.ranges) { + // for (size_t i = range.first; i < range.second; ++i) { + // active_region_data.idxs.push_back(i); + // } + // } + + // The size of the iteration domain is one less than the number of active rows since the final value of the + // grand product is constructed only in the relation and not explicitly in the polynomial + size_t active_domain_size = + active_region_data.ranges.empty() ? domain_size - 1 : active_region_data.idxs.size() - 1; const MultithreadData active_range_thread_data = calculate_thread_data(active_domain_size); @@ -100,8 +123,9 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, const size_t end = active_range_thread_data.end[thread_idx]; typename Flavor::AllValues row; for (size_t i = start; i < end; ++i) { - // TODO(https://github.com/AztecProtocol/barretenberg/issues/940):consider avoiding get_row if possible. - auto row_idx = active_idxs[i]; + // TODO(https://github.com/AztecProtocol/barretenberg/issues/940):consider avoiding get_row if + // possible. + auto row_idx = get_active_range_poly_idx(i); if constexpr (IsUltraFlavor) { row = full_polynomials.get_row_for_permutation_arg(row_idx); } else { @@ -183,7 +207,7 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, const size_t start = active_range_thread_data.start[thread_idx]; const size_t end = active_range_thread_data.end[thread_idx]; for (size_t i = start; i < end; ++i) { - auto poly_idx = active_idxs[i + 1]; + auto poly_idx = get_active_range_poly_idx(i + 1); grand_product_polynomial.at(poly_idx) = numerator[i] * denominator[i]; } }); @@ -193,24 +217,27 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, // active region that follows MultithreadData full_domain_thread_data = calculate_thread_data(domain_size); + // WORKTODO: just dont do this if a ctive ranges havent been set // Lambda to set the constant inactive regions of the grand product if they exist auto set_constant_value_if_inactive = [&](size_t i) { - for (size_t j = 0; j < active_block_ranges.size() - 1; ++j) { - if (i >= active_block_ranges[j].second && i < active_block_ranges[j + 1].first) { - size_t constant_value_idx = active_block_ranges[j + 1].first; + for (size_t j = 0; j < active_region_data.ranges.size() - 1; ++j) { + if (i >= active_region_data.ranges[j].second && i < active_region_data.ranges[j + 1].first) { + size_t constant_value_idx = active_region_data.ranges[j + 1].first; grand_product_polynomial.at(i) = grand_product_polynomial[constant_value_idx]; break; } } }; - parallel_for(full_domain_thread_data.num_threads, [&](size_t thread_idx) { - const size_t start = full_domain_thread_data.start[thread_idx]; - const size_t end = full_domain_thread_data.end[thread_idx]; - for (size_t i = start; i < end; ++i) { - set_constant_value_if_inactive(i); - } - }); + if (!active_region_data.ranges.empty()) { + parallel_for(full_domain_thread_data.num_threads, [&](size_t thread_idx) { + const size_t start = full_domain_thread_data.start[thread_idx]; + const size_t end = full_domain_thread_data.end[thread_idx]; + for (size_t i = start; i < end; ++i) { + set_constant_value_if_inactive(i); + } + }); + } DEBUG_LOG_ALL(grand_product_polynomial.coeffs()); } diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp index 87bef410f3f..e53e2bef64b 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp @@ -152,7 +152,7 @@ template class ProtogalaxyTests : public testing::Test { std::vector betas = { FF(5), FF(8), FF(11) }; std::vector deltas = { FF(2), FF(4), FF(8) }; std::vector full_honk_evaluations = { FF(1), FF(1), FF(1), FF(1), FF(1), FF(1), FF(1), FF(1) }; - [[maybe_unused]] Polynomial honk_evaluations_poly(full_honk_evaluations.size()); + Polynomial honk_evaluations_poly(full_honk_evaluations.size()); for (auto [poly_val, val] : zip_view(honk_evaluations_poly.coeffs(), full_honk_evaluations)) { poly_val = val; } @@ -564,12 +564,7 @@ template class ProtogalaxyTests : public testing::Test { EXPECT_TRUE(check_accumulator_target_sum_manual(prover_accumulator)); // Tamper with an accumulator polynomial - for (size_t i = 0; i < prover_accumulator->proving_key.circuit_size; ++i) { - if (prover_accumulator->proving_key.polynomials.q_arith[i] != 0) { - prover_accumulator->proving_key.polynomials.w_l.at(i) += 1; - break; - } - } + prover_accumulator->proving_key.polynomials.w_l.at(1) = FF::random_element(); EXPECT_FALSE(check_accumulator_target_sum_manual(prover_accumulator)); TupleOfKeys insts_2 = construct_keys(1); // just one decider key pair diff --git a/barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/protogalaxy_recursive_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/protogalaxy_recursive_verifier.test.cpp index 5c7f414336e..18e8643ab3b 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/protogalaxy_recursive_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/protogalaxy_recursive_verifier.test.cpp @@ -386,13 +386,8 @@ template class ProtogalaxyRecursiveTests : public tes auto verification_key = std::make_shared(prover_inst->proving_key); auto verifier_inst = std::make_shared(verification_key); - // Tamper with a non-trivial wire value in the accumulator - for (size_t i = 0; i < prover_accumulator->proving_key.circuit_size; ++i) { - if (prover_accumulator->proving_key.polynomials.q_arith[i] != 0) { - prover_accumulator->proving_key.polynomials.w_l.at(i) += 1; - break; - } - } + // Corrupt a wire value in the accumulator + prover_accumulator->proving_key.polynomials.w_l.at(1) = FF::random_element(&engine); // Generate a folding proof with the incorrect polynomials which would result in the prover having the wrong // target sum diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_flavor.hpp index e3d025af820..51919396de9 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_flavor.hpp @@ -510,7 +510,7 @@ class MegaFlavor { // Compute permutation grand product polynomial compute_grand_product>( - this->polynomials, relation_parameters, size_override, this->active_block_ranges); + this->polynomials, relation_parameters, size_override, this->active_region_data); } uint64_t estimate_memory() diff --git a/barretenberg/cpp/src/barretenberg/trace_to_polynomials/trace_to_polynomials.cpp b/barretenberg/cpp/src/barretenberg/trace_to_polynomials/trace_to_polynomials.cpp index 2321dcb7736..0e4aeddef79 100644 --- a/barretenberg/cpp/src/barretenberg/trace_to_polynomials/trace_to_polynomials.cpp +++ b/barretenberg/cpp/src/barretenberg/trace_to_polynomials/trace_to_polynomials.cpp @@ -105,9 +105,9 @@ typename TraceToPolynomials::TraceData TraceToPolynomials::const if constexpr (IsUltraFlavor) { // Mega and Ultra PROFILE_THIS_NAME("construct_active_indices"); if (block.size() > 0) { - proving_key.active_block_ranges.emplace_back(offset, offset + block.size()); + proving_key.active_region_data.ranges.emplace_back(offset, offset + block.size()); for (uint32_t i = offset; i < offset + block.size(); ++i) { - proving_key.active_idxs.push_back(i); + proving_key.active_region_data.idxs.push_back(i); } } } diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.cpp index 7377c7b31c7..0d80e535bb6 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.cpp @@ -98,13 +98,13 @@ template void OinkProver::execute_wire_commitment // We only commit to the fourth wire polynomial after adding memory recordss { PROFILE_THIS_NAME("COMMIT::wires"); - if (proving_key->get_is_structured()) { + if (IsMegaFlavor && proving_key->get_is_structured()) { witness_commitments.w_l = proving_key->proving_key.commitment_key->commit_structured( - proving_key->proving_key.polynomials.w_l, proving_key->proving_key.active_block_ranges); + proving_key->proving_key.polynomials.w_l, proving_key->proving_key.active_region_data.ranges); witness_commitments.w_r = proving_key->proving_key.commitment_key->commit_structured( - proving_key->proving_key.polynomials.w_r, proving_key->proving_key.active_block_ranges); + proving_key->proving_key.polynomials.w_r, proving_key->proving_key.active_region_data.ranges); witness_commitments.w_o = proving_key->proving_key.commitment_key->commit_structured( - proving_key->proving_key.polynomials.w_o, proving_key->proving_key.active_block_ranges); + proving_key->proving_key.polynomials.w_o, proving_key->proving_key.active_region_data.ranges); } else { witness_commitments.w_l = proving_key->proving_key.commitment_key->commit(proving_key->proving_key.polynomials.w_l); @@ -176,7 +176,7 @@ template void OinkProver::execute_sorted_list_acc PROFILE_THIS_NAME("COMMIT::wires"); if (proving_key->get_is_structured()) { witness_commitments.w_4 = proving_key->proving_key.commitment_key->commit_structured( - proving_key->proving_key.polynomials.w_4, proving_key->proving_key.active_block_ranges); + proving_key->proving_key.polynomials.w_4, proving_key->proving_key.active_region_data.ranges); } else { witness_commitments.w_4 = proving_key->proving_key.commitment_key->commit(proving_key->proving_key.polynomials.w_4); @@ -245,7 +245,7 @@ template void OinkProver::execute_grand_product_c witness_commitments.z_perm = proving_key->proving_key.commitment_key->commit_structured_with_nonzero_complement( proving_key->proving_key.polynomials.z_perm, - proving_key->proving_key.active_block_ranges, + proving_key->proving_key.active_region_data.ranges, proving_key->final_active_wire_idx + 1); } else { witness_commitments.z_perm = From bf1394d7c37dae6bd5a01e389306e56d7d6cb7c2 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Tue, 7 Jan 2025 14:52:20 +0000 Subject: [PATCH 20/24] more cleanup --- .../cpp/src/barretenberg/constants.hpp | 4 -- .../cpp/src/barretenberg/flavor/flavor.hpp | 8 +++ .../src/barretenberg/goblin/mock_circuits.hpp | 1 - .../composer/permutation_lib.hpp | 2 +- .../library/grand_product_library.hpp | 65 +++++++------------ .../trace_to_polynomials.cpp | 5 +- 6 files changed, 33 insertions(+), 52 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/constants.hpp b/barretenberg/cpp/src/barretenberg/constants.hpp index c8316fae31f..218761ae550 100644 --- a/barretenberg/cpp/src/barretenberg/constants.hpp +++ b/barretenberg/cpp/src/barretenberg/constants.hpp @@ -17,10 +17,6 @@ static constexpr uint32_t MAX_LOOKUP_TABLES_SIZE = 75000; static constexpr uint32_t MAX_DATABUS_SIZE = 10000; -// DEBUG -// static constexpr uint32_t MAX_LOOKUP_TABLES_SIZE = 8; -// static constexpr uint32_t MAX_DATABUS_SIZE = 2; - // The number of entries in ProverPolynomials reserved for randomness intended to mask witness commitments, witness // evaluation at the sumcheck challenge, and, if necessary, the evaluation of the corresponding shift static constexpr uint32_t MASKING_OFFSET = 4; diff --git a/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp b/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp index 09b3a796f6b..3d822b96f59 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp @@ -102,6 +102,14 @@ class PrecomputedEntitiesBase { struct ActiveRegionData { std::vector> ranges; // active ranges [start_i, end_i) of the execution trace std::vector idxs; // full set of poly indices corresposponding to active ranges + + void add_range(const size_t start, const size_t end) + { + ranges.emplace_back(start, end); + for (size_t i = start; i < end; ++i) { + idxs.push_back(i); + } + } }; /** diff --git a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp index cfa0be29d3a..67bc05e351d 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp @@ -190,7 +190,6 @@ class GoblinMockCircuits { static void construct_simple_circuit(MegaBuilder& builder) { PROFILE_THIS(); - // DEBUG add_some_ecc_op_gates(builder); MockCircuits::construct_arithmetic_circuit(builder); } diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/composer/permutation_lib.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/composer/permutation_lib.hpp index 3660eff0028..51d17040888 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/composer/permutation_lib.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/composer/permutation_lib.hpp @@ -226,7 +226,7 @@ void compute_honk_style_permutation_lagrange_polynomials_from_mapping( size_t domain_size = proving_key->active_region_data.idxs.size(); - const MultithreadData thread_data = calculate_thread_data(domain_size, /*min_iterations_per_thread=*/1 << 5); + const MultithreadData thread_data = calculate_thread_data(domain_size); size_t wire_idx = 0; for (auto& current_permutation_poly : permutation_polynomials) { diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp index 8ece3a1c371..89e27c6278c 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp @@ -49,11 +49,17 @@ namespace bb { * * Note: Step (3) utilizes Montgomery batch inversion to replace n-many inversions with * + * @note This method makes use of the fact that there are at most as many unique entries in the grand product as active + * rows in the execution trace to efficiently compute the grand product when a structured trace is in use. I.e. the + * computation peformed herein is proportional to the number of active rows in the trace and the constant values in the + * inactive regions are simply populated from known values on the last step. + * * @tparam Flavor * @tparam GrandProdRelation * @param full_polynomials * @param relation_parameters * @param size_override optional size of the domain; otherwise based on dyadic polynomial domain + * @param active_region_data optional specification of active region of execution trace */ template void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, @@ -67,49 +73,25 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, using Polynomial = typename Flavor::Polynomial; using Accumulator = std::tuple_element_t<0, typename GrandProdRelation::SumcheckArrayOfValuesOverSubrelations>; + const bool active_region_specified = !active_region_data.ranges.empty(); + // Set the domain over which the grand product must be computed. This may be less than the dyadic circuit size, e.g // the permutation grand product does not need to be computed beyond the index of the last active wire size_t domain_size = size_override == 0 ? full_polynomials.get_polynomial_size() : size_override; - // // If no active ranges have been specified, define the whole domain as the single active range - // if (active_region_data.ranges.empty()) { - // active_region_data.ranges.emplace_back(0, domain_size); - // } - - // auto execute_parallel_for_on_active_domain = [&](size_t num_iterations, const std::function& func) - // { - // MultithreadData thread_data; - - // if (active_region_data.ranges.empty()) { - // thread_data = calculate_thread_data(domain_size); - // parallel_for(thread_data.num_threads, func) {} - // else - // { - // } - // }; - // }; - + // Returns the ith active index if specified, otherwise acts as the identity map on the input auto get_active_range_poly_idx = [&](size_t i) { - if (active_region_data.idxs.empty()) { - return i; + if (active_region_specified) { + return active_region_data.idxs[i]; } - return active_region_data.idxs[i]; + return i; }; - // // Explicitly construct the indices of the active rows - // std::vector active_region_data.idxs; - // for (auto& range : active_region_data.ranges) { - // for (size_t i = range.first; i < range.second; ++i) { - // active_region_data.idxs.push_back(i); - // } - // } + size_t active_domain_size = active_region_specified ? active_region_data.idxs.size() : domain_size; // The size of the iteration domain is one less than the number of active rows since the final value of the // grand product is constructed only in the relation and not explicitly in the polynomial - size_t active_domain_size = - active_region_data.ranges.empty() ? domain_size - 1 : active_region_data.idxs.size() - 1; - - const MultithreadData active_range_thread_data = calculate_thread_data(active_domain_size); + const MultithreadData active_range_thread_data = calculate_thread_data(active_domain_size - 1); // Allocate numerator/denominator polynomials that will serve as scratch space // TODO(zac) we can re-use the permutation polynomial as the numerator polynomial. Reduces readability @@ -212,24 +194,23 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, } }); - // Final step: The grand product is constant in the inactive regions of the trace (since there are no copy - // constraints there). These constant values have already been computed and are equal to the first value in the - // active region that follows - MultithreadData full_domain_thread_data = calculate_thread_data(domain_size); - - // WORKTODO: just dont do this if a ctive ranges havent been set // Lambda to set the constant inactive regions of the grand product if they exist auto set_constant_value_if_inactive = [&](size_t i) { for (size_t j = 0; j < active_region_data.ranges.size() - 1; ++j) { - if (i >= active_region_data.ranges[j].second && i < active_region_data.ranges[j + 1].first) { - size_t constant_value_idx = active_region_data.ranges[j + 1].first; - grand_product_polynomial.at(i) = grand_product_polynomial[constant_value_idx]; + size_t previous_range_end = active_region_data.ranges[j].second; + size_t next_range_start = active_region_data.ranges[j + 1].first; + if (i >= previous_range_end && i < next_range_start) { + grand_product_polynomial.at(i) = grand_product_polynomial[next_range_start]; break; } } }; - if (!active_region_data.ranges.empty()) { + // Final step: The grand product is constant in the inactive regions of the trace (if they exist) where no copy + // constraints are present. These constant values have already been computed and are equal to the first value in the + // subsequent active region. + if (active_region_specified) { + MultithreadData full_domain_thread_data = calculate_thread_data(domain_size); parallel_for(full_domain_thread_data.num_threads, [&](size_t thread_idx) { const size_t start = full_domain_thread_data.start[thread_idx]; const size_t end = full_domain_thread_data.end[thread_idx]; diff --git a/barretenberg/cpp/src/barretenberg/trace_to_polynomials/trace_to_polynomials.cpp b/barretenberg/cpp/src/barretenberg/trace_to_polynomials/trace_to_polynomials.cpp index 0e4aeddef79..02c3bec4406 100644 --- a/barretenberg/cpp/src/barretenberg/trace_to_polynomials/trace_to_polynomials.cpp +++ b/barretenberg/cpp/src/barretenberg/trace_to_polynomials/trace_to_polynomials.cpp @@ -105,10 +105,7 @@ typename TraceToPolynomials::TraceData TraceToPolynomials::const if constexpr (IsUltraFlavor) { // Mega and Ultra PROFILE_THIS_NAME("construct_active_indices"); if (block.size() > 0) { - proving_key.active_region_data.ranges.emplace_back(offset, offset + block.size()); - for (uint32_t i = offset; i < offset + block.size(); ++i) { - proving_key.active_region_data.idxs.push_back(i); - } + proving_key.active_region_data.add_range(offset, offset + block.size()); } } From b104bc6c67f5691a383215781f371ffc1135862a Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Tue, 7 Jan 2025 19:37:15 +0000 Subject: [PATCH 21/24] clean and remove debug code --- .../execution_trace/mega_execution_trace.hpp | 15 --------- .../library/grand_product_library.hpp | 32 +++++++++---------- .../ultra_honk/mega_honk.test.cpp | 18 ++--------- .../barretenberg/ultra_honk/oink_prover.cpp | 2 +- 4 files changed, 20 insertions(+), 47 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/execution_trace/mega_execution_trace.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/execution_trace/mega_execution_trace.hpp index d5880a64b05..e1d31a9fac1 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/execution_trace/mega_execution_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/execution_trace/mega_execution_trace.hpp @@ -240,21 +240,6 @@ class MegaExecutionTraceBlocks : public MegaTraceBlockData { inline static const std::vector selector_names = {}; }; -/** - * @brief A micro structuring (for testing without recursive verifications only) - */ -static constexpr TraceStructure MICRO_TEST_STRUCTURE{ .ecc_op = 5, - .busread = 5, - .lookup = 2, - .pub_inputs = 1, - .arithmetic = 8, - .delta_range = 2, - .elliptic = 2, - .aux = 2, - .poseidon2_external = 2, - .poseidon2_internal = 2, - .overflow = 0 }; - /** * @brief A tiny structuring (for testing without recursive verifications only) */ diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp index 89e27c6278c..fd8aa337bdd 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp @@ -181,10 +181,13 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, // We have a 'virtual' 0 at the start (as this is a to-be-shifted polynomial) ASSERT(grand_product_polynomial.start_index() == 1); + // For Ultra/Mega, the first row is an inactive zero row thus the grand prod takes value 1 at both i = 0 and i = 1 if constexpr (IsUltraFlavor) { + ASSERT(active_region_data.idxs[0] == 1); // first active idx should be 1 grand_product_polynomial.at(1) = 1; } + // Compute grand product values corresponding only to the active regions of the trace parallel_for(active_range_thread_data.num_threads, [&](size_t thread_idx) { const size_t start = active_range_thread_data.start[thread_idx]; const size_t end = active_range_thread_data.end[thread_idx]; @@ -194,28 +197,25 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, } }); - // Lambda to set the constant inactive regions of the grand product if they exist - auto set_constant_value_if_inactive = [&](size_t i) { - for (size_t j = 0; j < active_region_data.ranges.size() - 1; ++j) { - size_t previous_range_end = active_region_data.ranges[j].second; - size_t next_range_start = active_region_data.ranges[j + 1].first; - if (i >= previous_range_end && i < next_range_start) { - grand_product_polynomial.at(i) = grand_product_polynomial[next_range_start]; - break; - } - } - }; - - // Final step: The grand product is constant in the inactive regions of the trace (if they exist) where no copy - // constraints are present. These constant values have already been computed and are equal to the first value in the - // subsequent active region. + // Final step: If active/inactive regions have been specified, the value of the grand product in the inactive + // regions have not yet been set. The polynomial takes an already computed constant value across each inactive + // region (since no copy constraints are present there) equal to the value of the grand product at the first index + // of the subsequent active region. if (active_region_specified) { MultithreadData full_domain_thread_data = calculate_thread_data(domain_size); parallel_for(full_domain_thread_data.num_threads, [&](size_t thread_idx) { const size_t start = full_domain_thread_data.start[thread_idx]; const size_t end = full_domain_thread_data.end[thread_idx]; for (size_t i = start; i < end; ++i) { - set_constant_value_if_inactive(i); + for (size_t j = 0; j < active_region_data.ranges.size() - 1; ++j) { + size_t previous_range_end = active_region_data.ranges[j].second; + size_t next_range_start = active_region_data.ranges[j + 1].first; + // If the index falls in an inactive region, set its value + if (i >= previous_range_end && i < next_range_start) { + grand_product_polynomial.at(i) = grand_product_polynomial[next_range_start]; + break; + } + } } }); } diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp index f0c825d4e7b..ab2917d65de 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp @@ -121,19 +121,16 @@ TYPED_TEST(MegaHonkTests, BasicStructured) // Construct and verify Honk proof using a structured trace TraceSettings trace_settings{ SMALL_TEST_STRUCTURE }; - // TraceSettings trace_settings{ MICRO_TEST_STRUCTURE }; auto proving_key = std::make_shared>(builder, trace_settings); Prover prover(proving_key); auto verification_key = std::make_shared(proving_key->proving_key); Verifier verifier(verification_key); auto proof = prover.construct_proof(); - RelationChecker::check_all(proving_key->proving_key.polynomials, proving_key->relation_parameters); + // Sanity check: ensure z_perm is not zero everywhere + EXPECT_TRUE(!proving_key->proving_key.polynomials.z_perm.is_zero()); - // for (size_t i = 0; i < proving_key->proving_key.circuit_size; ++i) { - // info("i = ", i, ", z_perm = ", proving_key->proving_key.polynomials.z_perm[i]); - // info("i = ", i, ", sigma_1 = ", proving_key->proving_key.polynomials.sigma_1[i]); - // } + RelationChecker::check_all(proving_key->proving_key.polynomials, proving_key->relation_parameters); EXPECT_TRUE(verifier.verify_proof(proof)); } @@ -178,15 +175,6 @@ TYPED_TEST(MegaHonkTests, DynamicVirtualSizeIncrease) Verifier verifier(verification_key); auto proof = prover.construct_proof(); - bool z_perm_nonzero = false; - for (size_t i = 0; i < circuit_size; ++i) { - if (proving_key->proving_key.polynomials.z_perm[i] != 0) { - z_perm_nonzero = true; - break; - } - } - EXPECT_TRUE(z_perm_nonzero); - RelationChecker::check_all(proving_key->proving_key.polynomials, proving_key->relation_parameters); EXPECT_TRUE(verifier.verify_proof(proof)); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.cpp index 0d80e535bb6..23836a739e8 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.cpp @@ -98,7 +98,7 @@ template void OinkProver::execute_wire_commitment // We only commit to the fourth wire polynomial after adding memory recordss { PROFILE_THIS_NAME("COMMIT::wires"); - if (IsMegaFlavor && proving_key->get_is_structured()) { + if (proving_key->get_is_structured()) { witness_commitments.w_l = proving_key->proving_key.commitment_key->commit_structured( proving_key->proving_key.polynomials.w_l, proving_key->proving_key.active_region_data.ranges); witness_commitments.w_r = proving_key->proving_key.commitment_key->commit_structured( From e702d003c988baf70f9038627adef10577b7639d Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Tue, 7 Jan 2025 22:33:34 +0000 Subject: [PATCH 22/24] remove problematic assert --- .../plonk_honk_shared/library/grand_product_library.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp index fd8aa337bdd..0d523b38c52 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp @@ -183,7 +183,6 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, // For Ultra/Mega, the first row is an inactive zero row thus the grand prod takes value 1 at both i = 0 and i = 1 if constexpr (IsUltraFlavor) { - ASSERT(active_region_data.idxs[0] == 1); // first active idx should be 1 grand_product_polynomial.at(1) = 1; } From d34fe9c29b0bf502efdddf1833e2a3e4e79dc2ea Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Wed, 8 Jan 2025 17:20:39 +0000 Subject: [PATCH 23/24] clean --- .../library/grand_product_library.hpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp index 0d523b38c52..6da2bd8e69b 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp @@ -80,12 +80,7 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, size_t domain_size = size_override == 0 ? full_polynomials.get_polynomial_size() : size_override; // Returns the ith active index if specified, otherwise acts as the identity map on the input - auto get_active_range_poly_idx = [&](size_t i) { - if (active_region_specified) { - return active_region_data.idxs[i]; - } - return i; - }; + auto get_active_range_poly_idx = [&](size_t i) { return active_region_specified ? active_region_data.idxs[i] : i; }; size_t active_domain_size = active_region_specified ? active_region_data.idxs.size() : domain_size; @@ -105,8 +100,7 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, const size_t end = active_range_thread_data.end[thread_idx]; typename Flavor::AllValues row; for (size_t i = start; i < end; ++i) { - // TODO(https://github.com/AztecProtocol/barretenberg/issues/940):consider avoiding get_row if - // possible. + // TODO(https://github.com/AztecProtocol/barretenberg/issues/940):consider avoiding get_row if possible. auto row_idx = get_active_range_poly_idx(i); if constexpr (IsUltraFlavor) { row = full_polynomials.get_row_for_permutation_arg(row_idx); From e442a51cd8385fbe35f9fbadad45000ff61ca61c Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Thu, 9 Jan 2025 15:58:22 +0000 Subject: [PATCH 24/24] make active region class more robust and constify some things --- .../cpp/src/barretenberg/flavor/flavor.hpp | 16 +++++++++++++--- .../composer/permutation_lib.hpp | 6 +++--- .../library/grand_product_library.hpp | 18 +++++++++--------- .../barretenberg/ultra_honk/oink_prover.cpp | 10 +++++----- 4 files changed, 30 insertions(+), 20 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp b/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp index 8a6c9114a4a..35092b67aeb 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp @@ -100,16 +100,26 @@ class PrecomputedEntitiesBase { }; // Specifies the regions of the execution trace containing non-trivial wire values struct ActiveRegionData { - std::vector> ranges; // active ranges [start_i, end_i) of the execution trace - std::vector idxs; // full set of poly indices corresposponding to active ranges - void add_range(const size_t start, const size_t end) { + ASSERT(start >= current_end); // ranges should be non-overlapping and increasing ranges.emplace_back(start, end); for (size_t i = start; i < end; ++i) { idxs.push_back(i); } + current_end = end; } + + std::vector> get_ranges() const { return ranges; } + size_t get_idx(const size_t idx) const { return idxs[idx]; } + std::pair get_range(const size_t idx) const { return ranges.at(idx); } + size_t size() const { return idxs.size(); } + size_t num_ranges() const { return ranges.size(); } + + private: + std::vector> ranges; // active ranges [start_i, end_i) of the execution trace + std::vector idxs; // full set of poly indices corresposponding to active ranges + size_t current_end{ 0 }; // end of last range; for ensuring monotonicity of ranges }; /** diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/composer/permutation_lib.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/composer/permutation_lib.hpp index 51d17040888..a2f2e4a813f 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/composer/permutation_lib.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/composer/permutation_lib.hpp @@ -224,7 +224,7 @@ void compute_honk_style_permutation_lagrange_polynomials_from_mapping( using FF = typename Flavor::FF; const size_t num_gates = proving_key->circuit_size; - size_t domain_size = proving_key->active_region_data.idxs.size(); + size_t domain_size = proving_key->active_region_data.size(); const MultithreadData thread_data = calculate_thread_data(domain_size); @@ -234,8 +234,8 @@ void compute_honk_style_permutation_lagrange_polynomials_from_mapping( const size_t start = thread_data.start[j]; const size_t end = thread_data.end[j]; for (size_t i = start; i < end; ++i) { - size_t poly_idx = proving_key->active_region_data.idxs[i]; - auto idx = static_cast(poly_idx); + const size_t poly_idx = proving_key->active_region_data.get_idx(i); + const auto idx = static_cast(poly_idx); const auto& current_row_idx = permutation_mappings[wire_idx].row_idx[idx]; const auto& current_col_idx = permutation_mappings[wire_idx].col_idx[idx]; const auto& current_is_tag = permutation_mappings[wire_idx].is_tag[idx]; diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp index 6da2bd8e69b..3bdd810136a 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp @@ -73,16 +73,16 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, using Polynomial = typename Flavor::Polynomial; using Accumulator = std::tuple_element_t<0, typename GrandProdRelation::SumcheckArrayOfValuesOverSubrelations>; - const bool active_region_specified = !active_region_data.ranges.empty(); + const bool has_active_ranges = active_region_data.size() > 0; // Set the domain over which the grand product must be computed. This may be less than the dyadic circuit size, e.g // the permutation grand product does not need to be computed beyond the index of the last active wire size_t domain_size = size_override == 0 ? full_polynomials.get_polynomial_size() : size_override; // Returns the ith active index if specified, otherwise acts as the identity map on the input - auto get_active_range_poly_idx = [&](size_t i) { return active_region_specified ? active_region_data.idxs[i] : i; }; + auto get_active_range_poly_idx = [&](size_t i) { return has_active_ranges ? active_region_data.get_idx(i) : i; }; - size_t active_domain_size = active_region_specified ? active_region_data.idxs.size() : domain_size; + size_t active_domain_size = has_active_ranges ? active_region_data.size() : domain_size; // The size of the iteration domain is one less than the number of active rows since the final value of the // grand product is constructed only in the relation and not explicitly in the polynomial @@ -185,7 +185,7 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, const size_t start = active_range_thread_data.start[thread_idx]; const size_t end = active_range_thread_data.end[thread_idx]; for (size_t i = start; i < end; ++i) { - auto poly_idx = get_active_range_poly_idx(i + 1); + const auto poly_idx = get_active_range_poly_idx(i + 1); grand_product_polynomial.at(poly_idx) = numerator[i] * denominator[i]; } }); @@ -194,16 +194,16 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, // regions have not yet been set. The polynomial takes an already computed constant value across each inactive // region (since no copy constraints are present there) equal to the value of the grand product at the first index // of the subsequent active region. - if (active_region_specified) { + if (has_active_ranges) { MultithreadData full_domain_thread_data = calculate_thread_data(domain_size); parallel_for(full_domain_thread_data.num_threads, [&](size_t thread_idx) { const size_t start = full_domain_thread_data.start[thread_idx]; const size_t end = full_domain_thread_data.end[thread_idx]; for (size_t i = start; i < end; ++i) { - for (size_t j = 0; j < active_region_data.ranges.size() - 1; ++j) { - size_t previous_range_end = active_region_data.ranges[j].second; - size_t next_range_start = active_region_data.ranges[j + 1].first; - // If the index falls in an inactive region, set its value + for (size_t j = 0; j < active_region_data.num_ranges() - 1; ++j) { + const size_t previous_range_end = active_region_data.get_range(j).second; + const size_t next_range_start = active_region_data.get_range(j + 1).first; + // Set the value of the polynomial if the index falls in an inactive region if (i >= previous_range_end && i < next_range_start) { grand_product_polynomial.at(i) = grand_product_polynomial[next_range_start]; break; diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.cpp index 741dbf201d3..0bdb08edacf 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.cpp @@ -100,11 +100,11 @@ template void OinkProver::execute_wire_commitment PROFILE_THIS_NAME("COMMIT::wires"); if (proving_key->get_is_structured()) { witness_commitments.w_l = proving_key->proving_key.commitment_key->commit_structured( - proving_key->proving_key.polynomials.w_l, proving_key->proving_key.active_region_data.ranges); + proving_key->proving_key.polynomials.w_l, proving_key->proving_key.active_region_data.get_ranges()); witness_commitments.w_r = proving_key->proving_key.commitment_key->commit_structured( - proving_key->proving_key.polynomials.w_r, proving_key->proving_key.active_region_data.ranges); + proving_key->proving_key.polynomials.w_r, proving_key->proving_key.active_region_data.get_ranges()); witness_commitments.w_o = proving_key->proving_key.commitment_key->commit_structured( - proving_key->proving_key.polynomials.w_o, proving_key->proving_key.active_region_data.ranges); + proving_key->proving_key.polynomials.w_o, proving_key->proving_key.active_region_data.get_ranges()); } else { witness_commitments.w_l = proving_key->proving_key.commitment_key->commit(proving_key->proving_key.polynomials.w_l); @@ -176,7 +176,7 @@ template void OinkProver::execute_sorted_list_acc PROFILE_THIS_NAME("COMMIT::wires"); if (proving_key->get_is_structured()) { witness_commitments.w_4 = proving_key->proving_key.commitment_key->commit_structured( - proving_key->proving_key.polynomials.w_4, proving_key->proving_key.active_region_data.ranges); + proving_key->proving_key.polynomials.w_4, proving_key->proving_key.active_region_data.get_ranges()); } else { witness_commitments.w_4 = proving_key->proving_key.commitment_key->commit(proving_key->proving_key.polynomials.w_4); @@ -245,7 +245,7 @@ template void OinkProver::execute_grand_product_c witness_commitments.z_perm = proving_key->proving_key.commitment_key->commit_structured_with_nonzero_complement( proving_key->proving_key.polynomials.z_perm, - proving_key->proving_key.active_region_data.ranges, + proving_key->proving_key.active_region_data.get_ranges(), proving_key->final_active_wire_idx + 1); } else { witness_commitments.z_perm =