Skip to content

Commit

Permalink
feat: Keshas skipping plus conditions for grand prod relations (#5766)
Browse files Browse the repository at this point in the history
Adds Kesha's relation skipping approach for Sumcheck only (i.e. full
proof construction / decider), not for folding. My only addition is a
condition for skipping the permutation relation. (I added a condition
for skipping the lookup relation but it leads to erratic failures in
acir tests that I couldn't explain. Details written into an
[issue](#952)).

Closes: #870 (Taking
advantage of sorted trace in sumcheck)

Master bench:
```
---------------------------------------------------------------------------------------
Benchmark                                             Time             CPU   Iterations
---------------------------------------------------------------------------------------
construct_proof_ultrahonk/sha256                    426 ms          397 ms            2
construct_proof_ultrahonk/keccak                   1627 ms         1517 ms            1
construct_proof_ultrahonk/ecdsa_verification       2974 ms         2754 ms            1
construct_proof_ultrahonk/merkle_membership         237 ms          219 ms            3
construct_proof_ultrahonk_power_of_2/15             249 ms          231 ms            3
construct_proof_ultrahonk_power_of_2/16             455 ms          427 ms            2
construct_proof_ultrahonk_power_of_2/17             886 ms          831 ms            1
construct_proof_ultrahonk_power_of_2/18            1762 ms         1657 ms            1
construct_proof_ultrahonk_power_of_2/19            3428 ms         3211 ms            1
construct_proof_ultrahonk_power_of_2/20            6752 ms         6344 ms            1
```

Branch:
```
---------------------------------------------------------------------------------------
Benchmark                                             Time             CPU   Iterations
---------------------------------------------------------------------------------------
construct_proof_ultrahonk/sha256                    330 ms          262 ms            3
construct_proof_ultrahonk/keccak                   1212 ms         1036 ms            1
construct_proof_ultrahonk/ecdsa_verification       2311 ms         1980 ms            1
construct_proof_ultrahonk/merkle_membership         191 ms          158 ms            4
construct_proof_ultrahonk_power_of_2/15             191 ms          176 ms            4
construct_proof_ultrahonk_power_of_2/16             342 ms          316 ms            2
construct_proof_ultrahonk_power_of_2/17             664 ms          614 ms            1
construct_proof_ultrahonk_power_of_2/18            1271 ms         1174 ms            1
construct_proof_ultrahonk_power_of_2/19            2542 ms         2332 ms            1
construct_proof_ultrahonk_power_of_2/20            4944 ms         4540 ms            1
```
  • Loading branch information
ledwards2225 authored and AztecBot committed Apr 24, 2024
1 parent fb44a35 commit 40fdf90
Show file tree
Hide file tree
Showing 12 changed files with 110 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -259,8 +259,6 @@ template <typename FF_> class UltraHonkArith {
UltraHonkTraceBlock ecc_op;
UltraHonkTraceBlock pub_inputs;
UltraHonkTraceBlock arithmetic;
// TODO(https://github.com/AztecProtocol/barretenberg/issues/919): Change: DeltaRangeConstraint -->
// DeltaRangeConstraint
UltraHonkTraceBlock delta_range;
UltraHonkTraceBlock elliptic;
UltraHonkTraceBlock aux;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ void compute_grand_product(const size_t circuit_size,
const size_t end = (thread_idx + 1) * block_size;
typename Flavor::AllValues evaluations;
auto evaluations_view = evaluations.get_all();
// TODO(https://github.com/AztecProtocol/barretenberg/issues/940): construction of evaluations is equivalent to
// calling get_row which creates full copies. avoid?
for (size_t i = start; i < end; ++i) {
for (auto [eval, full_poly] : zip_view(evaluations_view, full_polynomials_view)) {
eval = full_poly.size() > i ? full_poly[i] : 0;
Expand Down
9 changes: 9 additions & 0 deletions cpp/src/barretenberg/relations/auxiliary_relation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,15 @@ template <typename FF_> class AuxiliaryRelationImpl {
1 // RAM consistency sub-relation 3
};

/**
* @brief Returns true if the contribution from all subrelations for the provided inputs is identically zero
*
*/
template <typename AllEntities> inline static bool skip(const AllEntities& in)
{
return (in.q_aux.value_at(0).is_zero() && in.q_aux.value_at(1).is_zero());
}

/**
* @brief Expression for the generalized permutation sort gate.
* @details The following explanation is reproduced from the Plonk analog 'plookup_auxiliary_widget':
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@ template <typename FF_> class DeltaRangeConstraintRelationImpl {
6 // range constrain sub-relation 4
};

/**
* @brief Returns true if the contribution from all subrelations for the provided inputs is identically zero
*
*/
template <typename AllEntities> inline static bool skip(const AllEntities& in)
{
return (in.q_delta_range.value_at(0).is_zero() && in.q_delta_range.value_at(1).is_zero());
}

/**
* @brief Expression for the generalized permutation sort gate.
* @details The relation is defined as C(in(X)...) =
Expand Down
9 changes: 9 additions & 0 deletions cpp/src/barretenberg/relations/elliptic_relation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@ template <typename FF_> class EllipticRelationImpl {
6, // y-coordinate sub-relation
};

/**
* @brief Returns true if the contribution from all subrelations for the provided inputs is identically zero
*
*/
template <typename AllEntities> inline static bool skip(const AllEntities& in)
{
return (in.q_elliptic.value_at(0).is_zero() && in.q_elliptic.value_at(1).is_zero());
}

// TODO(@zac-williamson #2609 find more generic way of doing this)
static constexpr FF get_curve_b()
{
Expand Down
12 changes: 12 additions & 0 deletions cpp/src/barretenberg/relations/lookup_relation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,18 @@ template <typename FF_> class LookupRelationImpl {
4, // grand product construction sub-relation
0 // left-shiftable polynomial sub-relation
};

/**
* @brief Returns true if the contribution from all subrelations for the provided inputs is identically zero
*
*/
template <typename AllEntities> inline static bool skip([[maybe_unused]] const AllEntities& in)
{
// TODO(https://github.com/AztecProtocol/barretenberg/issues/952): figure out why skip condition described in
// issue causes failures in acir tests.
return false;
}

/**
* @brief Get the grand product polynomial object (either from the proving key or AllEntities depending on context)
*
Expand Down
12 changes: 12 additions & 0 deletions cpp/src/barretenberg/relations/permutation_relation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,18 @@ template <typename FF_> class UltraPermutationRelationImpl {
0 // left-shiftable polynomial sub-relation
};

/**
* @brief Returns true if the contribution from all subrelations for the provided inputs is identically zero
*
*/
template <typename AllEntities> inline static bool skip(const AllEntities& in)
{
// If z_perm == z_perm_shift, this implies that none of the wire values for the present input are involved in
// non-trivial copy constraints.
return (in.z_perm.value_at(0) == in.z_perm_shift.value_at(0) &&
in.z_perm.value_at(1) == in.z_perm_shift.value_at(1));
}

inline static auto& get_grand_product_polynomial(auto& in) { return in.z_perm; }
inline static auto& get_shifted_grand_product_polynomial(auto& in) { return in.z_perm_shift; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@ template <typename FF_> class Poseidon2ExternalRelationImpl {
7, // external poseidon2 round sub-relation for fourth value
};

/**
* @brief Returns true if the contribution from all subrelations for the provided inputs is identically zero
*
*/
template <typename AllEntities> inline static bool skip(const AllEntities& in)
{
return (in.q_poseidon2_external.value_at(0).is_zero() && in.q_poseidon2_external.value_at(1).is_zero());
}

/**
* @brief Expression for the poseidon2 external round relation, based on E_i in Section 6 of
* https://eprint.iacr.org/2023/323.pdf.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@ template <typename FF_> class Poseidon2InternalRelationImpl {
7, // internal poseidon2 round sub-relation for fourth value
};

/**
* @brief Returns true if the contribution from all subrelations for the provided inputs is identically zero
*
*/
template <typename AllEntities> inline static bool skip(const AllEntities& in)
{
return (in.q_poseidon2_internal.value_at(0).is_zero() && in.q_poseidon2_internal.value_at(1).is_zero());
}

/**
* @brief Expression for the poseidon2 internal round relation, based on I_i in Section 6 of
* https://eprint.iacr.org/2023/323.pdf.
Expand Down
15 changes: 15 additions & 0 deletions cpp/src/barretenberg/relations/relation_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,21 @@ consteval std::array<size_t, NUM_SUBRELATIONS> compute_composed_subrelation_part
*
*/

/**
* @brief Check if the relation has a static skip method to determine if accumulation of its result can be
* optimised away based on a single check
*
* @details The skip function should return true if relation can be skipped and false if it can't
* @tparam Relation The relation type
* @tparam AllEntities The type containing UnivariateViews with witness and selector values
*/
template <typename Relation, typename AllEntities>
concept isSkippable = requires(const AllEntities& input) {
{
Relation::is_active(input)
} -> std::same_as<bool>;
};

/**
* @brief A wrapper for Relations to expose methods used by the Sumcheck prover or verifier to add the
* contribution of a given relation to the corresponding accumulator.
Expand Down
9 changes: 9 additions & 0 deletions cpp/src/barretenberg/relations/ultra_arithmetic_relation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@ template <typename FF_> class UltraArithmeticRelationImpl {
5 // secondary arithmetic sub-relation
};

/**
* @brief Returns true if the contribution from all subrelations for the provided inputs is identically zero
*
*/
template <typename AllEntities> inline static bool skip(const AllEntities& in)
{
return (in.q_arith.value_at(0).is_zero() && in.q_arith.value_at(1).is_zero());
}

/**
* @brief Expression for the Ultra Arithmetic gate.
* @details This relation encapsulates several idenitities, toggled by the value of q_arith in [0, 1, 2, 3, ...].
Expand Down
17 changes: 15 additions & 2 deletions cpp/src/barretenberg/sumcheck/sumcheck_round.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -237,8 +237,21 @@ template <typename Flavor> class SumcheckProverRound {
const FF& scaling_factor)
{
using Relation = std::tuple_element_t<relation_idx, Relations>;
Relation::accumulate(
std::get<relation_idx>(univariate_accumulators), extended_edges, relation_parameters, scaling_factor);

// Check if the relation is skippable to speed up accumulation
if constexpr (!isSkippable<Relation, decltype(extended_edges)>) {
// If not, accumulate normally
Relation::accumulate(
std::get<relation_idx>(univariate_accumulators), extended_edges, relation_parameters, scaling_factor);
} else {
// If so, only compute the contribution if the relation is active
if (!Relation::skip(extended_edges, relation_parameters)) {
Relation::accumulate(std::get<relation_idx>(univariate_accumulators),
extended_edges,
relation_parameters,
scaling_factor);
}
}

// Repeat for the next relation.
if constexpr (relation_idx + 1 < NUM_RELATIONS) {
Expand Down

0 comments on commit 40fdf90

Please sign in to comment.