Skip to content

Commit

Permalink
refactor(bb): use RefArray where possible (#4686)
Browse files Browse the repository at this point in the history
5.7% speedup on ivc_bench due to no allocations in hot loop

---------

Co-authored-by: ludamad <[email protected]>
  • Loading branch information
ludamad and ludamad0 authored Feb 21, 2024
1 parent 920fa10 commit 5b4e1a6
Show file tree
Hide file tree
Showing 23 changed files with 1,179 additions and 1,072 deletions.
1 change: 1 addition & 0 deletions barretenberg/cpp/CMakePresets.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
"displayName": "Build with GCC",
"description": "Build with globally installed GCC",
"inherits": "default",
"binaryDir": "build-gcc",
"environment": {
"CC": "gcc",
"CXX": "g++"
Expand Down
2 changes: 1 addition & 1 deletion barretenberg/cpp/dockerfiles/Dockerfile.x86_64-linux-gcc
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ RUN cmake --preset gcc -DCI=ON && cmake --build --preset gcc

FROM alpine:3.18
RUN apk update && apk add libstdc++
COPY --from=builder /usr/src/barretenberg/cpp/build/bin/bb /usr/src/barretenberg/cpp/build/bin/bb
COPY --from=builder /usr/src/barretenberg/cpp/build-gcc/bin/bb /usr/src/barretenberg/cpp/build/bin/bb
2 changes: 1 addition & 1 deletion barretenberg/cpp/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
endif()

if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
add_compile_options(-fconstexpr-ops-limit=100000000)
add_compile_options(-fconstexpr-ops-limit=100000000 -Wno-psabi)
endif()

# We enable -O1 level optimsations, even when compiling debug wasm, otherwise we get "local count too large" at runtime.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once
#include "barretenberg/commitment_schemes/commitment_key.hpp"
#include "barretenberg/common/ref_span.hpp"
#include "barretenberg/common/ref_vector.hpp"
#include "barretenberg/common/zip_view.hpp"
#include "barretenberg/polynomials/polynomial.hpp"
Expand Down Expand Up @@ -316,15 +317,15 @@ template <typename Curve> class ZeroMorphProver_ {
* @param commitment_key
* @param transcript
*/
static void prove(const std::vector<Polynomial>& f_polynomials,
const std::vector<Polynomial>& g_polynomials,
const std::vector<FF>& f_evaluations,
const std::vector<FF>& g_shift_evaluations,
const std::vector<FF>& multilinear_challenge,
static void prove(RefSpan<Polynomial> f_polynomials,
RefSpan<Polynomial> g_polynomials,
RefSpan<FF> f_evaluations,
RefSpan<FF> g_shift_evaluations,
std::span<FF> multilinear_challenge,
const std::shared_ptr<CommitmentKey<Curve>>& commitment_key,
const std::shared_ptr<NativeTranscript>& transcript,
const std::vector<Polynomial>& concatenated_polynomials = {},
const std::vector<FF>& concatenated_evaluations = {},
RefSpan<Polynomial> concatenated_polynomials = {},
RefSpan<FF> concatenated_evaluations = {},
const std::vector<RefVector<Polynomial>>& concatenation_groups = {})
{
// Generate batching challenge \rho and powers 1,...,\rho^{m-1}
Expand Down Expand Up @@ -516,13 +517,13 @@ template <typename Curve> class ZeroMorphVerifier_ {
* @param concatenation_groups_commitments
* @return Commitment
*/
static Commitment compute_C_Z_x(const std::vector<Commitment>& f_commitments,
const std::vector<Commitment>& g_commitments,
std::vector<Commitment>& C_q_k,
static Commitment compute_C_Z_x(RefSpan<Commitment> f_commitments,
RefSpan<Commitment> g_commitments,
std::span<Commitment> C_q_k,
FF rho,
FF batched_evaluation,
FF x_challenge,
std::vector<FF> u_challenge,
std::span<FF> u_challenge,
const std::vector<RefVector<Commitment>>& concatenation_groups_commitments = {})
{
size_t log_N = C_q_k.size();
Expand Down Expand Up @@ -634,14 +635,14 @@ template <typename Curve> class ZeroMorphVerifier_ {
* @return std::array<Commitment, 2> Inputs to the final pairing check
*/
static std::array<Commitment, 2> verify(
auto&& unshifted_commitments,
auto&& to_be_shifted_commitments,
auto&& unshifted_evaluations,
auto&& shifted_evaluations,
auto& multivariate_challenge,
RefSpan<Commitment> unshifted_commitments,
RefSpan<Commitment> to_be_shifted_commitments,
RefSpan<FF> unshifted_evaluations,
RefSpan<FF> shifted_evaluations,
std::span<FF> multivariate_challenge,
auto& transcript,
const std::vector<RefVector<Commitment>>& concatenation_group_commitments = {},
const std::vector<FF>& concatenated_evaluations = {})
RefSpan<FF> concatenated_evaluations = {})
{
size_t log_N = multivariate_challenge.size();
FF rho = transcript->template get_challenge<FF>("rho");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,19 +78,23 @@ template <class Curve> class ZeroMorphTest : public CommitmentTest<Curve> {
auto prover_transcript = NativeTranscript::prover_init_empty();

// Execute Prover protocol
ZeroMorphProver::prove(f_polynomials,
g_polynomials,
v_evaluations,
w_evaluations,
ZeroMorphProver::prove(RefVector(f_polynomials),
RefVector(g_polynomials),
RefVector(v_evaluations),
RefVector(w_evaluations),
u_challenge,
this->commitment_key,
prover_transcript);

auto verifier_transcript = NativeTranscript::verifier_init_empty(prover_transcript);

// Execute Verifier protocol
auto pairing_points = ZeroMorphVerifier::verify(
f_commitments, g_commitments, v_evaluations, w_evaluations, u_challenge, verifier_transcript);
auto pairing_points = ZeroMorphVerifier::verify(RefVector(f_commitments),
RefVector(g_commitments),
RefVector(v_evaluations),
RefVector(w_evaluations),
u_challenge,
verifier_transcript);

bool verified = this->vk()->pairing_check(pairing_points[0], pairing_points[1]);

Expand Down Expand Up @@ -224,28 +228,28 @@ template <class Curve> class ZeroMorphWithConcatenationTest : public CommitmentT
auto prover_transcript = NativeTranscript::prover_init_empty();

// Execute Prover protocol
ZeroMorphProver::prove(f_polynomials, // unshifted
g_polynomials, // to-be-shifted
v_evaluations, // unshifted
w_evaluations, // shifted
ZeroMorphProver::prove(RefVector(f_polynomials), // unshifted
RefVector(g_polynomials), // to-be-shifted
RefVector(v_evaluations), // unshifted
RefVector(w_evaluations), // shifted
u_challenge,
this->commitment_key,
prover_transcript,
concatenated_polynomials,
c_evaluations,
RefVector(concatenated_polynomials),
RefVector(c_evaluations),
to_vector_of_ref_vectors(concatenation_groups));

auto verifier_transcript = NativeTranscript::verifier_init_empty(prover_transcript);

// Execute Verifier protocol
auto pairing_points = ZeroMorphVerifier::verify(f_commitments, // unshifted
g_commitments, // to-be-shifted
v_evaluations, // unshifted
w_evaluations, // shifted
auto pairing_points = ZeroMorphVerifier::verify(RefVector(f_commitments), // unshifted
RefVector(g_commitments), // to-be-shifted
RefVector(v_evaluations), // unshifted
RefVector(w_evaluations), // shifted
u_challenge,
verifier_transcript,
to_vector_of_ref_vectors(concatenation_groups_commitments),
c_evaluations);
RefVector(c_evaluations));

verified = this->vk()->pairing_check(pairing_points[0], pairing_points[1]);

Expand Down
22 changes: 17 additions & 5 deletions barretenberg/cpp/src/barretenberg/common/ref_array.hpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
#pragma once

#include "barretenberg/common/assert.hpp"
#include <array>
#include <cstddef>
#include <initializer_list>
#include <iterator>
#include <span>
#include <stdexcept>

namespace bb {
Expand All @@ -18,6 +21,7 @@ namespace bb {
*/
template <typename T, std::size_t N> class RefArray {
public:
RefArray() = default;
RefArray(const std::array<T*, N>& ptr_array)
{
std::size_t i = 0;
Expand Down Expand Up @@ -55,7 +59,11 @@ template <typename T, std::size_t N> class RefArray {
, pos(pos)
{}

T& operator*() const { return (*array)[pos]; }
T& operator*() const
{
ASSERT(pos < N);
return (*array)[pos];
}

iterator& operator++()
{
Expand Down Expand Up @@ -92,6 +100,9 @@ template <typename T, std::size_t N> class RefArray {
*/
iterator end() const { return iterator(this, N); }

T** get_storage() { return storage; }
T* const* get_storage() const { return storage; }

private:
// We are making a high-level array, for simplicity having a C array as backing makes sense.
// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays)
Expand All @@ -115,24 +126,25 @@ template <typename T, typename... Ts> RefArray(T&, Ts&...) -> RefArray<T, 1 + si
* @param ref_arrays The RefArray objects to be concatenated.
* @return RefArray object containing all elements from the input arrays.
*/
template <typename T, std::size_t... Ns> RefArray<T, (Ns + ...)> concatenate(const RefArray<T, Ns>&... ref_arrays)
template <typename T, std::size_t... Ns>
RefArray<T, (Ns + ...)> constexpr concatenate(const RefArray<T, Ns>&... ref_arrays)
{
// Fold expression to calculate the total size of the new array using fold expression
constexpr std::size_t TotalSize = (Ns + ...);
std::array<T*, TotalSize> concatenated;
RefArray<T, TotalSize> concatenated;

std::size_t offset = 0;
// Copies elements from a given RefArray to the concatenated array
auto copy_into = [&](const auto& ref_array, std::size_t& offset) {
for (std::size_t i = 0; i < ref_array.size(); ++i) {
concatenated[offset + i] = &ref_array[i];
concatenated.get_storage()[offset + i] = &ref_array[i];
}
offset += ref_array.size();
};

// Fold expression to copy elements from each input RefArray to the concatenated array
(..., copy_into(ref_arrays, offset));

return RefArray<T, TotalSize>{ concatenated };
return concatenated;
}
} // namespace bb
100 changes: 100 additions & 0 deletions barretenberg/cpp/src/barretenberg/common/ref_span.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#pragma once

#include <cstddef>
#include <iterator>

#include "ref_array.hpp"
#include "ref_vector.hpp"

namespace bb {

template <typename T> class RefSpan {
public:
// Default constructor
RefSpan()
: storage(nullptr)
, array_size(0)
{}

template <std::size_t Size>
RefSpan(const RefArray<T, Size>& ref_array)
: storage(ref_array.get_storage())
, array_size(Size)
{}
RefSpan(const RefVector<T>& ref_vector)
: storage(&ref_vector.get_storage()[0])
, array_size(ref_vector.size())
{}

// Constructor from an array of pointers and size
RefSpan(T** ptr_array, std::size_t size)
: storage(ptr_array)
, array_size(size)
{}

// Copy constructor
RefSpan(const RefSpan& other) = default;

// Move constructor
RefSpan(RefSpan&& other) noexcept = default;

// Destructor
~RefSpan() = default;

// Copy assignment operator
RefSpan& operator=(const RefSpan& other) = default;

// Move assignment operator
RefSpan& operator=(RefSpan&& other) noexcept = default;

// Access element at index
T& operator[](std::size_t idx) const
{
// Assuming the caller ensures idx is within bounds.
return *storage[idx];
}

// Get size of the RefSpan
constexpr std::size_t size() const { return array_size; }

// Iterator implementation
class iterator {
public:
iterator(T* const* array, std::size_t pos)
: array(array)
, pos(pos)
{}

T& operator*() const { return *(array[pos]); }

iterator& operator++()
{
++pos;
return *this;
}

iterator operator++(int)
{
iterator temp = *this;
++(*this);
return temp;
}

bool operator==(const iterator& other) const { return pos == other.pos; }
bool operator!=(const iterator& other) const { return pos != other.pos; }

private:
T* const* array;
std::size_t pos;
};

// Begin and end for iterator support
iterator begin() const { return iterator(storage, 0); }
iterator end() const { return iterator(storage, array_size); }

private:
T* const* storage;
std::size_t array_size;
};

} // namespace bb
Loading

0 comments on commit 5b4e1a6

Please sign in to comment.