@@ -20,7 +20,10 @@ struct ExecutionTraceUsageTracker {
20
20
21
21
TraceStructure max_sizes; // max utilization of each block
22
22
MegaTraceFixedBlockSizes fixed_sizes; // fixed size of each block prescribed by structuring
23
- MegaTraceActiveRanges active_ranges; // ranges utlized by the accumulator within the ambient structured trace
23
+ // Store active ranges based on the most current accumulator and those based on all but the most recently
24
+ // accumulated circuit. The former is needed for the combiner calculation and the latter for the perturbator.
25
+ std::vector<Range> active_ranges;
26
+ std::vector<Range> previous_active_ranges;
24
27
25
28
std::vector<Range> thread_ranges; // ranges within the ambient space over which utilized space is evenly distibuted
26
29
@@ -60,36 +63,39 @@ struct ExecutionTraceUsageTracker {
60
63
max_tables_size = std::max (max_tables_size, circuit.get_tables_size ());
61
64
62
65
// Update the active ranges of the trace based on max block utilization
63
- for (auto [max_size, fixed_block, active_range] :
64
- zip_view (max_sizes.get (), fixed_sizes.get (), active_ranges.get ())) {
66
+ previous_active_ranges = active_ranges; // store active ranges based on all but the present circuit
67
+ active_ranges.clear ();
68
+ for (auto [max_size, fixed_block] : zip_view (max_sizes.get (), fixed_sizes.get ())) {
65
69
size_t start_idx = fixed_block.trace_offset ;
66
70
size_t end_idx = start_idx + max_size;
67
- active_range = Range{ start_idx, end_idx };
71
+ active_ranges. push_back ( Range{ start_idx, end_idx }) ;
68
72
}
69
73
70
- // The active ranges for the databus and lookup relations (both based on log-deriv lookup argument) must
71
- // incorporate both the lookup/read gate blocks as well as the rows containing the data that is being read.
72
- // Update the corresponding ranges accordingly. (Note: tables are constructed at the 'bottom' of the trace).
74
+ // The active ranges must also include the rows where the actual databus and lookup table data are stored.
75
+ // (Note: lookup tables are constructed at the end of the trace; databus data is constructed at the start).
73
76
size_t dyadic_circuit_size = fixed_sizes.get_structured_dyadic_size ();
74
- active_ranges.busread .first = 0 ; // databus data is stored at the top of the trace
75
- active_ranges.busread .second = std::max (max_databus_size, active_ranges.busread .second );
76
- active_ranges.lookup .first = std::min (dyadic_circuit_size - max_tables_size, active_ranges.lookup .first );
77
- active_ranges.lookup .second = dyadic_circuit_size; // lookups are stored at the bottom of the trace
77
+
78
+ // TODO(https://github.com/AztecProtocol/barretenberg/issues/1152): should be able to use simply Range{ 0,
79
+ // max_databus_size } but this breaks for certain choices of num_threads.
80
+ size_t databus_end =
81
+ std::max (max_databus_size, static_cast <size_t >(fixed_sizes.busread .trace_offset + max_sizes.busread ));
82
+ active_ranges.push_back (Range{ 0 , databus_end });
83
+ size_t lookups_start =
84
+ std::min (dyadic_circuit_size - max_tables_size, static_cast <size_t >(fixed_sizes.lookup .trace_offset ));
85
+ active_ranges.push_back (Range{ lookups_start, dyadic_circuit_size });
78
86
}
79
87
80
- // Check whether an index is contained within the active ranges
81
- bool check_is_active (const size_t idx)
88
+ // Check whether an index is contained within the active ranges (or previous active ranges; needed for perturbator)
89
+ bool check_is_active (const size_t idx, bool use_prev_accumulator = false )
82
90
{
83
91
// If structured trace is not in use, assume the whole trace is active
84
92
if (!trace_settings.structure ) {
85
93
return true ;
86
94
}
87
- for (auto & range : active_ranges.get ()) {
88
- if (idx >= range.first && idx < range.second ) {
89
- return true ;
90
- }
91
- }
92
- return false ;
95
+ std::vector<Range> ranges_to_check = use_prev_accumulator ? previous_active_ranges : active_ranges;
96
+ return std::any_of (ranges_to_check.begin (), ranges_to_check.end (), [idx](const auto & range) {
97
+ return idx >= range.first && idx < range.second ;
98
+ });
93
99
}
94
100
95
101
// For printing only. Must match the order of the members in the arithmetization
@@ -117,7 +123,7 @@ struct ExecutionTraceUsageTracker {
117
123
void print_active_ranges ()
118
124
{
119
125
info (" Active regions of accumulator: " );
120
- for (auto [label, range] : zip_view (block_labels, active_ranges. get () )) {
126
+ for (auto [label, range] : zip_view (block_labels, active_ranges)) {
121
127
std::cout << std::left << std::setw (20 ) << (label + " :" ) << " (" << range.first << " , " << range.second
122
128
<< " )" << std::endl;
123
129
}
@@ -134,27 +140,25 @@ struct ExecutionTraceUsageTracker {
134
140
}
135
141
136
142
/* *
137
- * @brief Construct ranges of execution trace rows that evenly distribute the active content of the trace across a
143
+ * @brief Construct ranges of execution trace rows that evenly distribute the active content of the trace across a
138
144
* given number of threads.
139
145
*
140
146
* @param num_threads Num ranges over which to distribute the data
141
147
* @param full_domain_size Size of full domain; needed only for unstructured case
148
+ * @param use_prev_accumulator Base ranges on previous or current accumulator
142
149
*/
143
- void construct_thread_ranges (const size_t num_threads, const size_t full_domain_size)
150
+ void construct_thread_ranges (const size_t num_threads,
151
+ const size_t full_domain_size,
152
+ bool use_prev_accumulator = false )
144
153
{
145
- // Copy the ranges into a simple std container for processing by subsequent methods (cheap)
146
- std::vector<Range> active_ranges_copy;
147
- for (const auto & range : active_ranges.get ()) {
148
- active_ranges_copy.push_back (range);
149
- }
150
-
151
154
// Convert the active ranges for each gate type into a set of sorted non-overlapping ranges (union of the input)
152
155
std::vector<Range> simplified_active_ranges;
153
156
if (!trace_settings.structure ) {
154
157
// If not using a structured trace, set the active range to the whole domain
155
158
simplified_active_ranges.push_back (Range{ 0 , full_domain_size });
156
159
} else {
157
- simplified_active_ranges = construct_union_of_ranges (active_ranges_copy);
160
+ simplified_active_ranges = use_prev_accumulator ? construct_union_of_ranges (previous_active_ranges)
161
+ : construct_union_of_ranges (active_ranges);
158
162
}
159
163
160
164
// Determine ranges in the structured trace that even distibute the active content across threads
0 commit comments