Skip to content
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: Use structured polys to reduce prover memory #8587

Merged
merged 44 commits into from
Sep 26, 2024
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
ff435f3
changed the location of the allocation of the polynomials to where th…
lucasxia01 Sep 17, 2024
b184022
Merge branch 'master' into lx/structurize-prover-polys
lucasxia01 Sep 17, 2024
9942d6e
fix build
lucasxia01 Sep 17, 2024
aa6db5c
set to_be_shifted polys to start_idx=1 and some poly initializations …
lucasxia01 Sep 17, 2024
1362cb4
undo unnecessary shiftable call... which somehow fixes everything
lucasxia01 Sep 17, 2024
da06f55
fix a couple stray tests
lucasxia01 Sep 17, 2024
125d47c
Merge branch 'master' into lx/structurize-prover-polys
lucasxia01 Sep 17, 2024
e906410
structurized lagrange polys and selectors
lucasxia01 Sep 17, 2024
f01b646
add expand class that allows for the unstructured
lucasxia01 Sep 18, 2024
e1e949b
fix tests and allow for polynomials over different active ranges to a…
lucasxia01 Sep 18, 2024
9f5b8bb
fix mega test
lucasxia01 Sep 18, 2024
b045e61
adjust memory for ecc_op wires and selector
lucasxia01 Sep 18, 2024
3cb43fb
fix floating point issue with main.ts
lucasxia01 Sep 18, 2024
c689569
fix commit_sparse to handle non-power-of-two sizes and add new tests
lucasxia01 Sep 18, 2024
f95c018
reduce databus poly memory
lucasxia01 Sep 18, 2024
313c491
updated 4 table and 2 read_count polys
lucasxia01 Sep 18, 2024
f22f7ef
fix noir-packages-test
lucasxia01 Sep 18, 2024
fe91327
Merge remote-tracking branch 'origin/master' into lx/structurize-prov…
lucasxia01 Sep 19, 2024
8277038
remove accidental extra copy
lucasxia01 Sep 19, 2024
d7e7530
made inverse polys structured
lucasxia01 Sep 19, 2024
7e75ce6
Delete barretenberg/acir_tests/crs/grumpkin_size
lucasxia01 Sep 19, 2024
111a037
add issue for databus_id
lucasxia01 Sep 19, 2024
f1b5578
try using commit instead of commit_sparse for ecc_op and databus and …
lucasxia01 Sep 19, 2024
3770913
undo change with databus inverses
lucasxia01 Sep 19, 2024
1080eb6
small cleanup
lucasxia01 Sep 19, 2024
f8a6c00
new tests and cleanup
lucasxia01 Sep 19, 2024
56d36e7
more consts
lucasxia01 Sep 19, 2024
3c8d5d4
cleanup + adding trace_offset to blocks so things are cleaner
lucasxia01 Sep 20, 2024
746a58b
Merge branch 'master' into lx/structurize-prover-polys
lucasxia01 Sep 20, 2024
b4c30ea
Merge branch 'master' into lx/structurize-prover-polys
lucasxia01 Sep 21, 2024
a472716
fix analyze client ivc bench script
lucasxia01 Sep 21, 2024
e770973
tracy debugging
lucasxia01 Sep 23, 2024
1773af7
Merge remote-tracking branch 'origin/master' into lx/structurize-prov…
lucasxia01 Sep 24, 2024
648c014
update Crs size
lucasxia01 Sep 24, 2024
765b074
fix formatting
lucasxia01 Sep 24, 2024
7c193e6
make gate selectors and ecc_op_wires based on the fixed_size rather t…
lucasxia01 Sep 24, 2024
0b03bca
big refactor to allocate all polys in one place and also base sizes o…
lucasxia01 Sep 26, 2024
4162a8c
revert full()
lucasxia01 Sep 26, 2024
006da13
fix tests and small changes
lucasxia01 Sep 26, 2024
7d44083
revert poly tests and disable Expand test
lucasxia01 Sep 26, 2024
3a190d8
poly test fix
lucasxia01 Sep 26, 2024
de71b76
put public inputs stuff back for plonk
lucasxia01 Sep 26, 2024
33d65cb
Merge branch 'master' into lx/structurize-prover-polys
lucasxia01 Sep 26, 2024
8254e6a
clean up for merge
lucasxia01 Sep 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,61 @@ template <class Flavor>
typename ExecutionTrace_<Flavor>::TraceData ExecutionTrace_<Flavor>::construct_trace_data(
Builder& builder, typename Flavor::ProvingKey& proving_key, bool is_structured)
{
ZoneScopedN("construct_trace_data");
TraceData trace_data{ builder, proving_key };

// Complete the public inputs execution trace block from builder.public_inputs
populate_public_inputs_block(builder);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

switched the order so that we populate the public_inputs_block first


ZoneScopedN("construct_trace_data");
// Allocate the wires and selectors polynomials
if constexpr (IsHonkFlavor<Flavor>) {
for (auto& wire : proving_key.polynomials.get_wires()) {
wire = Polynomial::shiftable(proving_key.circuit_size);
}
// Define selectors over the block they are isolated to
uint32_t offset = Flavor::has_zero_row ? 1 : 0;
lucasxia01 marked this conversation as resolved.
Show resolved Hide resolved
if constexpr (IsGoblinFlavor<Flavor>) {
offset += builder.blocks.ecc_op.get_fixed_size(is_structured);
}
offset += builder.blocks.pub_inputs.get_fixed_size(is_structured);

proving_key.polynomials.q_arith =
Polynomial(proving_key.circuit_size - offset, proving_key.circuit_size, offset);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this because of the aux relation using q_arith? I don't see why circuit_size - offset would be the right thing here. (If the aux issue is relevant can you add a TODO with this issue I made while back)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh yeah this was me just checking that things worked. Forgot to set it to what it should be, which is the end of the aux block.

offset += builder.blocks.arithmetic.get_fixed_size(is_structured);

proving_key.polynomials.q_delta_range =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may not be an important optimization but my original vision was that the data in the block would simply become (or be moved into) the polynomial mem block. Not sure to what extent this is supported with the current poly implementation

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, I share that same vision. Was planning to try to do it in a followup PR

Polynomial(builder.blocks.delta_range.size(), proving_key.circuit_size, offset);
offset += builder.blocks.delta_range.get_fixed_size(is_structured);

proving_key.polynomials.q_elliptic =
Polynomial(builder.blocks.elliptic.size(), proving_key.circuit_size, offset);
offset += builder.blocks.elliptic.get_fixed_size(is_structured);

proving_key.polynomials.q_aux = Polynomial(builder.blocks.aux.size(), proving_key.circuit_size, offset);
offset += builder.blocks.aux.get_fixed_size(is_structured);

proving_key.polynomials.q_lookup = Polynomial(builder.blocks.lookup.size(), proving_key.circuit_size, offset);
offset += builder.blocks.lookup.get_fixed_size(is_structured);

if constexpr (HasDataBus<Flavor>) {
proving_key.polynomials.q_busread =
Polynomial(builder.blocks.busread.size(), proving_key.circuit_size, offset);
offset += builder.blocks.busread.get_fixed_size(is_structured);
}

proving_key.polynomials.q_poseidon2_external =
Polynomial(builder.blocks.poseidon2_external.size(), proving_key.circuit_size, offset);

offset += builder.blocks.poseidon2_external.get_fixed_size(is_structured);
proving_key.polynomials.q_poseidon2_internal =
Polynomial(builder.blocks.poseidon2_internal.size(), proving_key.circuit_size, offset);
offset += builder.blocks.poseidon2_internal.get_fixed_size(is_structured);
// Set the other selector polynomials to full size
for (auto& selector : proving_key.polynomials.get_non_gate_selectors()) {
selector = Polynomial(proving_key.circuit_size);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these along with the wires, sigmas, ids, and z_perm could be restricted to the actual circuit size and not the dyadic circuit_size.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is true but due to the nature of the structured trace I dont think this would ever be significant. Most we could save is the unused portion of the last block

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or potentially more if we don't even use some blocks (which means getting rid of the ensure_nonzero stuff)

}
}

TraceData trace_data{ builder, proving_key };

uint32_t offset = Flavor::has_zero_row ? 1 : 0; // Offset at which to place each block in the trace polynomials
// For each block in the trace, populate wire polys, copy cycles and selector polys

Expand Down Expand Up @@ -134,12 +183,20 @@ void ExecutionTrace_<Flavor>::add_ecc_op_wires_to_proving_key(Builder& builder,
typename Flavor::ProvingKey& proving_key)
requires IsGoblinFlavor<Flavor>
{
// Copy the ecc op data from the conventional wires into the op wires over the range of ecc op gates
auto& ecc_op_selector = proving_key.polynomials.lagrange_ecc_op;
const size_t op_wire_offset = Flavor::has_zero_row ? 1 : 0;
// Allocate the ecc op wires and selector
const size_t num_ecc_ops = builder.blocks.ecc_op.size();
if constexpr (IsHonkFlavor<Flavor>) {
for (auto& wire : proving_key.polynomials.get_ecc_op_wires()) {
wire = Polynomial(num_ecc_ops, proving_key.circuit_size, op_wire_offset);
}
ecc_op_selector = Polynomial(num_ecc_ops, proving_key.circuit_size, op_wire_offset);
}
// Copy the ecc op data from the conventional wires into the op wires over the range of ecc op gates
for (auto [ecc_op_wire, wire] :
zip_view(proving_key.polynomials.get_ecc_op_wires(), proving_key.polynomials.get_wires())) {
for (size_t i = 0; i < builder.blocks.ecc_op.size(); ++i) {
for (size_t i = 0; i < num_ecc_ops; ++i) {
size_t idx = i + op_wire_offset;
ecc_op_wire.at(idx) = wire[idx];
ecc_op_selector.at(idx) = 1; // construct selector as the indicator on the ecc op block
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ template <class Flavor> class ExecutionTrace_ {
for (auto [selector, other_selector] : zip_view(selectors, proving_key.polynomials.get_selectors())) {
selector = other_selector.share();
}
proving_key.polynomials.set_shifted(); // Ensure shifted wires are set correctly
lucasxia01 marked this conversation as resolved.
Show resolved Hide resolved
} else {
// Initialize and share the wire and selector polynomials
for (size_t idx = 0; idx < NUM_WIRES; ++idx) {
Expand Down
3 changes: 3 additions & 0 deletions barretenberg/cpp/src/barretenberg/flavor/flavor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,9 @@ concept IsGoblinFlavor = IsAnyOf<T, MegaFlavor,
MegaRecursiveFlavor_<UltraCircuitBuilder>,
MegaRecursiveFlavor_<MegaCircuitBuilder>, MegaRecursiveFlavor_<CircuitSimulatorBN254>>;

template <typename T>
concept HasDataBus = IsGoblinFlavor<T>;

template <typename T>
concept IsRecursiveFlavor = IsAnyOf<T, UltraRecursiveFlavor_<UltraCircuitBuilder>,
UltraRecursiveFlavor_<MegaCircuitBuilder>,
Expand Down
2 changes: 1 addition & 1 deletion barretenberg/cpp/src/barretenberg/flavor/flavor.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ TEST(Flavor, Getters)
// set
size_t coset_idx = 0;
for (auto& id_poly : proving_key.polynomials.get_ids()) {
typename Flavor::Polynomial new_poly(proving_key.circuit_size);
id_poly = typename Flavor::Polynomial(proving_key.circuit_size);
for (size_t i = 0; i < proving_key.circuit_size; ++i) {
id_poly.at(i) = coset_idx * proving_key.circuit_size + i;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,6 @@ template <typename FF, size_t NUM_WIRES, size_t NUM_SELECTORS> class ExecutionTr
bool has_ram_rom = false; // does the block contain RAM/ROM gates
bool is_pub_inputs = false; // is this the public inputs block

uint32_t fixed_size = 0; // Fixed size for use in structured trace

bool operator==(const ExecutionTraceBlock& other) const = default;

size_t size() const { return std::get<0>(this->wires).size(); }
Expand Down Expand Up @@ -104,6 +102,8 @@ template <typename FF, size_t NUM_WIRES, size_t NUM_SELECTORS> class ExecutionTr
}
}
#endif
private:
uint32_t fixed_size = 0; // Fixed size for use in structured trace
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

made this private to avoid accidentally getting it. Need to call get_fixed_size() instead because it's 0 in the unstructured case.

};

} // namespace bb
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ namespace bb {
template <typename Flavor>
void construct_lookup_table_polynomials(const RefArray<typename Flavor::Polynomial, 4>& table_polynomials,
const typename Flavor::CircuitBuilder& circuit,
size_t dyadic_circuit_size,
size_t additional_offset = 0)
const size_t dyadic_circuit_size,
const size_t additional_offset = 0)
{
// Create lookup selector polynomials which interpolate each table column.
// Our selector polys always need to interpolate the full subgroup size, so here we offset so as to
Expand All @@ -22,8 +22,16 @@ void construct_lookup_table_polynomials(const RefArray<typename Flavor::Polynomi
// | table randomness
// ignored, as used for regular constraints and padding to the next power of 2.
// TODO(https://github.com/AztecProtocol/barretenberg/issues/1033): construct tables and counts at top of trace
ASSERT(dyadic_circuit_size > circuit.get_tables_size() + additional_offset);
size_t offset = dyadic_circuit_size - circuit.get_tables_size() - additional_offset;
const size_t tables_size = circuit.get_tables_size();
ASSERT(dyadic_circuit_size > tables_size + additional_offset);
size_t offset = dyadic_circuit_size - tables_size - additional_offset;

// Allocate the table polynomials
if constexpr (IsHonkFlavor<Flavor>) {
for (auto& poly : table_polynomials) {
poly = typename Flavor::Polynomial(tables_size, dyadic_circuit_size, offset);
}
}

for (const auto& table : circuit.lookup_tables) {
const fr table_index(table.table_index);
Expand All @@ -49,12 +57,17 @@ template <typename Flavor>
void construct_lookup_read_counts(typename Flavor::Polynomial& read_counts,
typename Flavor::Polynomial& read_tags,
typename Flavor::CircuitBuilder& circuit,
size_t dyadic_circuit_size)
const size_t dyadic_circuit_size)
{
const size_t tables_size = circuit.get_tables_size();
// TODO(https://github.com/AztecProtocol/barretenberg/issues/1033): construct tables and counts at top of trace
size_t offset = dyadic_circuit_size - circuit.get_tables_size();
size_t table_offset = dyadic_circuit_size - tables_size;
// Allocate the read counts and tags polynomials
if constexpr (IsHonkFlavor<Flavor>) {
read_counts = typename Flavor::Polynomial(tables_size, dyadic_circuit_size, table_offset);
read_tags = typename Flavor::Polynomial(tables_size, dyadic_circuit_size, table_offset);
}

size_t table_offset = offset; // offset of the present table in the table polynomials
// loop over all tables used in the circuit; each table contains data about the lookups made on it
for (auto& table : circuit.lookup_tables) {
table.initialize_index_map();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,13 @@ void compute_permutation_argument_polynomials(const typename Flavor::CircuitBuil
compute_monomial_and_coset_fft_polynomials_from_lagrange<Flavor::NUM_WIRES>("id", key);
}
} else if constexpr (IsUltraFlavor<Flavor>) { // any UltraHonk flavor
// Allocate sigma and id polynomials
for (auto& sigma : key->polynomials.get_sigmas()) {
sigma = typename Flavor::Polynomial(key->circuit_size);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wasn't sure if I could restrict any of these

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could restrict to the non-dyadic circuit size potentially? Unsure because computing them iterates over the EvaluationDomain...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not much we can do here I dont think

}
for (auto& id : key->polynomials.get_ids()) {
id = typename Flavor::Polynomial(key->circuit_size);
}
// Compute Honk-style sigma and ID polynomials from the corresponding mappings
{
ZoneScopedN("compute_honk_style_permutation_lagrange_polynomials_from_mapping");
Expand Down
65 changes: 41 additions & 24 deletions barretenberg/cpp/src/barretenberg/polynomials/polynomial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ SharedShiftedVirtualZeroesArray<Fr> _clone(const SharedShiftedVirtualZeroesArray
template <typename Fr>
void Polynomial<Fr>::allocate_backing_memory(size_t size, size_t virtual_size, size_t start_index)
{
ASSERT(start_index + size <= virtual_size);
coefficients_ = SharedShiftedVirtualZeroesArray<Fr>{
start_index, /* start index, used for shifted polynomials and offset 'islands' of non-zeroes */
size + start_index, /* end index, actual memory used is (end - start) */
Expand Down Expand Up @@ -158,8 +159,9 @@ template <typename Fr> bool Polynomial<Fr>::operator==(Polynomial const& rhs) co
template <typename Fr> Polynomial<Fr>& Polynomial<Fr>::operator+=(PolynomialSpan<const Fr> other)
{
// Compute the subset that is defined in both polynomials
ASSERT(start_index() <= other.start_index);
ASSERT(end_index() >= other.end_index());
if (other.start_index < start_index() || other.end_index() > end_index()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did this situation arise? I'm wondering if its best to silently expand polys like this when it happens.. I'm assuming resizing the memory like this can pretty undesirable. Might be better to alert the user so that the memory can be allocated correctly in the first place. Maybe I'm missing some context tho

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this situation arises in the unstructured case because we end up folding polynomials with different active regions. You're right that this could be dangerous, but not sure how we could alert the user unless we throw an error... I think it would be unfortunate if we had to set the active regions of all polys to be the whole circuit size in the unstructured case.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note this can cause bugs because it breaks .share() functionality

*this = expand(std::min(start_index(), other.start_index), std::max(end_index(), other.end_index()));
}
size_t num_threads = calculate_num_threads(other.size());
size_t range_per_thread = other.size() / num_threads;
size_t leftovers = other.size() - (range_per_thread * num_threads);
Expand Down Expand Up @@ -287,14 +289,15 @@ Fr Polynomial<Fr>::compute_barycentric_evaluation(const Fr& z, const EvaluationD
template <typename Fr> Polynomial<Fr>& Polynomial<Fr>::operator-=(PolynomialSpan<const Fr> other)
{
// Compute the subset that is defined in both polynomials
ASSERT(start_index() <= other.start_index);
ASSERT(end_index() >= other.end_index());
size_t num_threads = calculate_num_threads(other.size());
size_t range_per_thread = other.size() / num_threads;
size_t leftovers = other.size() - (range_per_thread * num_threads);
if (other.start_index < start_index() || other.end_index() > end_index()) {
*this = expand(std::min(start_index(), other.start_index), std::max(end_index(), other.end_index()));
}
const size_t num_threads = calculate_num_threads(other.size());
const size_t range_per_thread = other.size() / num_threads;
const size_t leftovers = other.size() - (range_per_thread * num_threads);
parallel_for(num_threads, [&](size_t j) {
size_t offset = j * range_per_thread + other.start_index;
size_t end = (j == num_threads - 1) ? offset + range_per_thread + leftovers : offset + range_per_thread;
const size_t offset = j * range_per_thread + other.start_index;
const size_t end = (j == num_threads - 1) ? offset + range_per_thread + leftovers : offset + range_per_thread;
for (size_t i = offset; i < end; ++i) {
at(i) -= other[i];
}
Expand All @@ -304,12 +307,12 @@ template <typename Fr> Polynomial<Fr>& Polynomial<Fr>::operator-=(PolynomialSpan

template <typename Fr> Polynomial<Fr>& Polynomial<Fr>::operator*=(const Fr scaling_factor)
{
size_t num_threads = calculate_num_threads(size());
size_t range_per_thread = size() / num_threads;
size_t leftovers = size() - (range_per_thread * num_threads);
const size_t num_threads = calculate_num_threads(size());
const size_t range_per_thread = size() / num_threads;
const size_t leftovers = size() - (range_per_thread * num_threads);
parallel_for(num_threads, [&](size_t j) {
size_t offset = j * range_per_thread;
size_t end = (j == num_threads - 1) ? offset + range_per_thread + leftovers : offset + range_per_thread;
const size_t offset = j * range_per_thread;
const size_t end = (j == num_threads - 1) ? offset + range_per_thread + leftovers : offset + range_per_thread;
for (size_t i = offset; i < end; ++i) {
data()[i] *= scaling_factor;
}
Expand All @@ -318,24 +321,38 @@ template <typename Fr> Polynomial<Fr>& Polynomial<Fr>::operator*=(const Fr scali
return *this;
}

template <typename Fr> Polynomial<Fr> Polynomial<Fr>::full() const
template <typename Fr>
Polynomial<Fr> Polynomial<Fr>::expand(const size_t new_start_index, const size_t new_end_index) const
{
ASSERT(new_end_index <= virtual_size());
ASSERT(new_start_index <= start_index());
ASSERT(new_end_index >= end_index());
if (new_start_index == start_index() && new_end_index == end_index()) {
return *this;
}
Polynomial result = *this;
// Make 0..virtual_size usable
result.coefficients_ = _clone(coefficients_, virtual_size() - end_index(), start_index());
// Make new_start_index..new_end_index usable
result.coefficients_ = _clone(coefficients_, new_end_index - end_index(), start_index() - new_start_index);
return result;
}

template <typename Fr> Polynomial<Fr> Polynomial<Fr>::full() const
{
// Make 0..virtual_size usable
return expand(0, virtual_size());
}
template <typename Fr> void Polynomial<Fr>::add_scaled(PolynomialSpan<const Fr> other, Fr scaling_factor) &
{
// Compute the subset that is defined in both polynomials
ASSERT(start_index() <= other.start_index);
ASSERT(end_index() >= other.end_index());
size_t num_threads = calculate_num_threads(other.size());
size_t range_per_thread = other.size() / num_threads;
size_t leftovers = other.size() - (range_per_thread * num_threads);
if (other.start_index < start_index() || other.end_index() > end_index()) {
*this = expand(std::min(start_index(), other.start_index), std::max(end_index(), other.end_index()));
}
const size_t num_threads = calculate_num_threads(other.size());
const size_t range_per_thread = other.size() / num_threads;
const size_t leftovers = other.size() - (range_per_thread * num_threads);
parallel_for(num_threads, [&](size_t j) {
size_t offset = j * range_per_thread + other.start_index;
size_t end = (j == num_threads - 1) ? offset + range_per_thread + leftovers : offset + range_per_thread;
const size_t offset = j * range_per_thread + other.start_index;
const size_t end = (j == num_threads - 1) ? offset + range_per_thread + leftovers : offset + range_per_thread;
for (size_t i = offset; i < end; ++i) {
at(i) += scaling_factor * other[i];
}
Expand Down
8 changes: 8 additions & 0 deletions barretenberg/cpp/src/barretenberg/polynomials/polynomial.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,14 @@ template <typename Fr> class Polynomial {
return p;
}

/**
* @brief Expands the polynomial with new start_index and end_index
* The value of the polynomial remains the same, but defined memory region differs.
*
* @return a polynomial with a larger size() but same virtual_size()
*/
Polynomial expand(const size_t new_start_index, const size_t new_end_index) const;

/**
* @brief Copys the polynomial, but with the whole address space usable.
* The value of the polynomial remains the same, but defined memory region differs.
Expand Down
Loading
Loading