-
Notifications
You must be signed in to change notification settings - Fork 234
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(bb): towards reduced polynomial memory usage #7990
Changes from 150 commits
88cb0b4
3714e2e
3ddc166
67de114
9421093
b2cb0d8
ac72179
e3b8713
f9ce86b
d528cc0
428f0de
30c8e5c
496fdae
f9c7931
1552197
4f1e519
eaa6a34
50f59fe
d79914e
d83219e
cdeedc6
24b35f3
a3d18fb
23ff433
45ee50d
b3868e2
b6f6968
f3a7f60
8e4ece7
35fa784
5f347ca
da1baa9
d0b3918
99d672a
ebf2a90
6a6795e
5561f67
109146b
bbc3b84
55ded5b
549edb2
98bc35c
abff423
7fba8bd
a8023b0
0869084
70d194e
6932aac
195d845
8698df4
15d9184
44bd924
e682488
88c0c28
ede7f41
44c7f78
fdd2b29
e0e0153
95022c2
81503b3
9623ecf
5e99416
2770bcc
65f76b0
6ce46c4
d3a4498
d63fea1
73fa590
5616be3
bce13aa
57d4d81
956a794
cac72b1
bb6b7cc
d6d08d0
4a871b2
cf62795
01efa1f
5c8418a
cb8f5e6
536ebbe
528142a
c371e37
069c007
b1d4b79
84d7b74
94e6df3
7dc942b
25f64be
bf21caf
1b16007
55758d0
485d627
39a9525
47c7736
84cb602
00981cb
686c4a5
c3e37c5
ac15f5b
7dae750
a9c2617
49fa0ad
e791c97
2be10cd
6386e95
34425ea
70f03c5
7e518f8
80d568b
06c61cd
dd7e461
d720c55
e55bb85
1d306e8
52027b3
782f472
971a388
7dbd1d9
f5514c3
41c01c6
7f4ea77
e5bcec1
d1c7702
1457a3c
e307d13
5bbff94
c70ef6f
0f0b86f
c81ec3b
4192629
0e6c1b6
200a243
9573c93
2c6a6c6
4a2e3a8
f5b430e
27f1d36
2646dbc
f51042a
44dd297
e72cdbd
95e1c5e
60d111d
8bb094d
4e9e400
6047855
e16f609
7befd6d
f0e9ecd
964384c
b2a5423
bd0b6dc
a4f34cb
e1d8f4d
8f5af24
0b69ca6
5efcd7e
be4a79e
8adb0b6
213cc28
a45ab52
72d286c
92926cf
0ffcee2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,10 +7,12 @@ | |
* simplify the codebase. | ||
*/ | ||
|
||
#include "barretenberg/common/debug_log.hpp" | ||
#include "barretenberg/common/op_count.hpp" | ||
#include "barretenberg/ecc/scalar_multiplication/scalar_multiplication.hpp" | ||
#include "barretenberg/numeric/bitop/get_msb.hpp" | ||
#include "barretenberg/numeric/bitop/pow.hpp" | ||
#include "barretenberg/polynomials/polynomial.hpp" | ||
#include "barretenberg/polynomials/polynomial_arithmetic.hpp" | ||
#include "barretenberg/srs/factories/crs_factory.hpp" | ||
#include "barretenberg/srs/factories/file_crs_factory.hpp" | ||
|
@@ -79,20 +81,30 @@ template <class Curve> class CommitmentKey { | |
* @param polynomial a univariate polynomial p(X) = ∑ᵢ aᵢ⋅Xⁱ | ||
* @return Commitment computed as C = [p(x)] = ∑ᵢ aᵢ⋅Gᵢ | ||
*/ | ||
Commitment commit(std::span<const Fr> polynomial) | ||
Commitment commit(PolynomialSpan<const Fr> polynomial) | ||
{ | ||
BB_OP_COUNT_TIME(); | ||
// See constructor, we must round up the number of used srs points to a power of 2. | ||
const size_t consumed_srs = numeric::round_up_power_2(polynomial.size()); | ||
// WORKTODO(sparse) rework this - should we always inform how much SRS we need on-demand? | ||
ludamad marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// We must have a power-of-2 SRS points *after* subtracting by start_index. | ||
const size_t consumed_srs = numeric::round_up_power_2(polynomial.size()) + polynomial.start_index; | ||
auto srs = crs_factory->get_prover_crs(consumed_srs); | ||
// We only need the | ||
if (consumed_srs > srs->get_monomial_size()) { | ||
info("Attempting to commit to a polynomial that needs ", | ||
consumed_srs, | ||
" points with an SRS of size ", | ||
srs->get_monomial_size()); | ||
ASSERT(false); | ||
throw_or_abort(format("Attempting to commit to a polynomial that needs ", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't see the utility of continuing on after realizing this size is not enough. Actually, there is security risk whenever we knowingly read past allocated memory. |
||
consumed_srs, | ||
" points with an SRS of size ", | ||
srs->get_monomial_size())); | ||
} | ||
return scalar_multiplication::pippenger_unsafe_optimized_for_non_dyadic_polys<Curve>( | ||
polynomial, srs->get_monomial_points(), pippenger_runtime_state); | ||
|
||
// Extract the precomputed point table (contains raw SRS points at even indices and the corresponding | ||
// endomorphism point (\beta*x, -y) at odd indices). We offset by polynomial.start_index * 2 to align | ||
// with our polynomial span. | ||
std::span<G1> point_table = srs->get_monomial_points().subspan(polynomial.start_index * 2); | ||
DEBUG_LOG_ALL(polynomial.span); | ||
Commitment point = scalar_multiplication::pippenger_unsafe_optimized_for_non_dyadic_polys<Curve>( | ||
polynomial.span, point_table, pippenger_runtime_state); | ||
DEBUG_LOG(point); | ||
return point; | ||
}; | ||
|
||
/** | ||
|
@@ -105,19 +117,20 @@ template <class Curve> class CommitmentKey { | |
* @param polynomial | ||
* @return Commitment | ||
*/ | ||
Commitment commit_sparse(std::span<const Fr> polynomial) | ||
Commitment commit_sparse(PolynomialSpan<const Fr> polynomial) | ||
{ | ||
BB_OP_COUNT_TIME(); | ||
const size_t degree = polynomial.size(); | ||
ASSERT(degree <= srs->get_monomial_size()); | ||
const size_t poly_size = polynomial.size(); | ||
ASSERT(polynomial.end_index() <= srs->get_monomial_size()); | ||
|
||
// Extract the precomputed point table (contains raw SRS points at even indices and the corresponding | ||
// endomorphism point (\beta*x, -y) at odd indices). | ||
std::span<G1> point_table = srs->get_monomial_points(); | ||
// endomorphism point (\beta*x, -y) at odd indices). We offset by polynomial.start_index * 2 to align | ||
// with our polynomial spann. | ||
std::span<G1> point_table = srs->get_monomial_points().subspan(polynomial.start_index * 2); | ||
|
||
// Define structures needed to multithread the extraction of non-zero inputs | ||
const size_t num_threads = degree >= get_num_cpus_pow2() ? get_num_cpus_pow2() : 1; | ||
const size_t block_size = degree / num_threads; | ||
const size_t num_threads = poly_size >= get_num_cpus_pow2() ? get_num_cpus_pow2() : 1; | ||
const size_t block_size = poly_size / num_threads; | ||
std::vector<std::vector<Fr>> thread_scalars(num_threads); | ||
std::vector<std::vector<G1>> thread_points(num_threads); | ||
|
||
|
@@ -128,7 +141,7 @@ template <class Curve> class CommitmentKey { | |
|
||
for (size_t idx = start; idx < end; ++idx) { | ||
|
||
const Fr& scalar = polynomial[idx]; | ||
const Fr& scalar = polynomial.span[idx]; | ||
|
||
if (!scalar.is_zero()) { | ||
thread_scalars[thread_idx].emplace_back(scalar); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -44,12 +44,13 @@ template <class Curve> class GeminiTest : public CommitmentTest<Curve> { | |
const size_t num_unshifted = multilinear_polynomials.size(); | ||
const size_t num_shifted = multilinear_polynomials_to_be_shifted.size(); | ||
for (size_t i = 0; i < num_unshifted; ++i) { | ||
batched_unshifted.add_scaled(multilinear_polynomials[i], rhos[i]); | ||
batched_unshifted.add_scaled({ /*start index*/ 0, multilinear_polynomials[i] }, rhos[i]); | ||
batched_commitment_unshifted += multilinear_commitments[i] * rhos[i]; | ||
} | ||
for (size_t i = 0; i < num_shifted; ++i) { | ||
size_t rho_idx = num_unshifted + i; | ||
batched_to_be_shifted.add_scaled(multilinear_polynomials_to_be_shifted[i], rhos[rho_idx]); | ||
batched_to_be_shifted.add_scaled({ /*start index*/ 0, multilinear_polynomials_to_be_shifted[i] }, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm hopeful that we can in general make tradeoffs on methods like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure I understand here, there is that check, but everything has start indices now whereas 0 was implicit before so I passed it There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah I get it. Will experiment There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have made it more strict as discussed |
||
rhos[rho_idx]); | ||
batched_commitment_to_be_shifted += multilinear_commitments_to_be_shifted[i] * rhos[rho_idx]; | ||
} | ||
|
||
|
@@ -113,13 +114,13 @@ TYPED_TEST(GeminiTest, Single) | |
const size_t log_n = 4; | ||
|
||
auto u = this->random_evaluation_point(log_n); | ||
auto poly = this->random_polynomial(n); | ||
auto poly = Polynomial<Fr>::random(n); | ||
auto commitment = this->commit(poly); | ||
auto eval = poly.evaluate_mle(u); | ||
|
||
// Collect multilinear polynomials evaluations, and commitments for input to prover/verifier | ||
std::vector<Fr> multilinear_evaluations = { eval }; | ||
std::vector<std::span<Fr>> multilinear_polynomials = { poly }; | ||
std::vector<std::span<Fr>> multilinear_polynomials = { poly.coeffs() }; | ||
std::vector<std::span<Fr>> multilinear_polynomials_to_be_shifted = {}; | ||
std::vector<GroupElement> multilinear_commitments = { commitment }; | ||
std::vector<GroupElement> multilinear_commitments_to_be_shifted = {}; | ||
|
@@ -144,16 +145,16 @@ TYPED_TEST(GeminiTest, SingleShift) | |
auto u = this->random_evaluation_point(log_n); | ||
|
||
// shiftable polynomial must have 0 as last coefficient | ||
auto poly = this->random_polynomial(n); | ||
poly[0] = Fr::zero(); | ||
auto poly = Polynomial<Fr>::random(n); | ||
poly.at(0) = Fr::zero(); | ||
|
||
auto commitment = this->commit(poly); | ||
auto eval_shift = poly.evaluate_mle(u, true); | ||
|
||
// Collect multilinear polynomials evaluations, and commitments for input to prover/verifier | ||
std::vector<Fr> multilinear_evaluations = { eval_shift }; | ||
std::vector<std::span<Fr>> multilinear_polynomials = {}; | ||
std::vector<std::span<Fr>> multilinear_polynomials_to_be_shifted = { poly }; | ||
std::vector<std::span<Fr>> multilinear_polynomials_to_be_shifted = { poly.coeffs() }; | ||
std::vector<GroupElement> multilinear_commitments = {}; | ||
std::vector<GroupElement> multilinear_commitments_to_be_shifted = { commitment }; | ||
|
||
|
@@ -176,8 +177,8 @@ TYPED_TEST(GeminiTest, Double) | |
|
||
auto u = this->random_evaluation_point(log_n); | ||
|
||
auto poly1 = this->random_polynomial(n); | ||
auto poly2 = this->random_polynomial(n); | ||
auto poly1 = Polynomial<Fr>::random(n); | ||
auto poly2 = Polynomial<Fr>::random(n); | ||
|
||
auto commitment1 = this->commit(poly1); | ||
auto commitment2 = this->commit(poly2); | ||
|
@@ -187,7 +188,7 @@ TYPED_TEST(GeminiTest, Double) | |
|
||
// Collect multilinear polynomials evaluations, and commitments for input to prover/verifier | ||
std::vector<Fr> multilinear_evaluations = { eval1, eval2 }; | ||
std::vector<std::span<Fr>> multilinear_polynomials = { poly1, poly2 }; | ||
std::vector<std::span<Fr>> multilinear_polynomials = { poly1.coeffs(), poly2.coeffs() }; | ||
std::vector<std::span<Fr>> multilinear_polynomials_to_be_shifted = {}; | ||
std::vector<GroupElement> multilinear_commitments = { commitment1, commitment2 }; | ||
std::vector<GroupElement> multilinear_commitments_to_be_shifted = {}; | ||
|
@@ -204,16 +205,16 @@ TYPED_TEST(GeminiTest, Double) | |
TYPED_TEST(GeminiTest, DoubleWithShift) | ||
{ | ||
using Fr = typename TypeParam::ScalarField; | ||
using Polynomial = typename bb::Polynomial<Fr>; | ||
using GroupElement = typename TypeParam::Element; | ||
|
||
const size_t n = 16; | ||
const size_t log_n = 4; | ||
|
||
auto u = this->random_evaluation_point(log_n); | ||
|
||
auto poly1 = this->random_polynomial(n); | ||
auto poly2 = this->random_polynomial(n); | ||
poly2[0] = Fr::zero(); // necessary for polynomial to be 'shiftable' | ||
auto poly1 = Polynomial::random(n); | ||
auto poly2 = Polynomial::random(n, 1); // make 'shiftable' | ||
|
||
auto commitment1 = this->commit(poly1); | ||
auto commitment2 = this->commit(poly2); | ||
|
@@ -224,8 +225,8 @@ TYPED_TEST(GeminiTest, DoubleWithShift) | |
|
||
// Collect multilinear polynomials evaluations, and commitments for input to prover/verifier | ||
std::vector<Fr> multilinear_evaluations = { eval1, eval2, eval2_shift }; | ||
std::vector<std::span<Fr>> multilinear_polynomials = { poly1, poly2 }; | ||
std::vector<std::span<Fr>> multilinear_polynomials_to_be_shifted = { poly2 }; | ||
std::vector<std::span<Fr>> multilinear_polynomials = { poly1.coeffs(), poly2.coeffs() }; | ||
std::vector<std::span<Fr>> multilinear_polynomials_to_be_shifted = { poly2.coeffs() }; | ||
std::vector<GroupElement> multilinear_commitments = { commitment1, commitment2 }; | ||
std::vector<GroupElement> multilinear_commitments_to_be_shifted = { commitment2 }; | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
snuck in this, some waiting logic so you can start multiple benchmarks and walk away