Skip to content

Commit 2911c0b

Browse files
committed
defer caching nnf ops to avoid race
1 parent fa713b9 commit 2911c0b

2 files changed

Lines changed: 26 additions & 2 deletions

File tree

barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_circuit_builder.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1576,15 +1576,20 @@ std::array<uint32_t, 2> UltraCircuitBuilder_<ExecutionTrace>::queue_partial_non_
15761576
const uint32_t hi_0_idx = this->add_variable(hi_0);
15771577
const uint32_t hi_1_idx = this->add_variable(hi_1);
15781578

1579-
// Add witnesses into the multiplication cache (duplicates removed during circuit finalization)
1579+
// Add witnesses into the multiplication cache (duplicates removed during circuit finalization).
1580+
// In cursor mode, defer to per-thread buffer to avoid races on the shared vector.
15801581
cached_partial_non_native_field_multiplication cache_entry{
15811582
.a = input.a,
15821583
.b = input.b,
15831584
.lo_0 = lo_0_idx,
15841585
.hi_0 = hi_0_idx,
15851586
.hi_1 = hi_1_idx,
15861587
};
1587-
cached_partial_non_native_field_multiplications.emplace_back(cache_entry);
1588+
if (this->get_variable_cursor() != this->VARIABLE_CURSOR_DISABLED) {
1589+
deferred_non_native_field_muls_[get_parallel_thread_index()].emplace_back(cache_entry);
1590+
} else {
1591+
cached_partial_non_native_field_multiplications.emplace_back(cache_entry);
1592+
}
15881593
return std::array<uint32_t, 2>{ lo_0_idx, hi_1_idx };
15891594
}
15901595

barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,13 +218,31 @@ class UltraCircuitBuilder_ : public CircuitBuilderBase<typename ExecutionTrace_:
218218
};
219219
std::vector<std::vector<DeferredRangeConstraint>> deferred_range_constraints_; // per-thread
220220

221+
// Deferred non-native field multiplications for parallel construction. In cursor mode,
222+
// these are buffered per-thread to avoid races on the shared vector.
223+
std::vector<std::vector<cached_partial_non_native_field_multiplication>> deferred_non_native_field_muls_;
224+
221225
/**
222226
* @brief Initialize deferred buffers for N threads.
223227
*/
224228
void init_deferred_buffers(size_t num_threads)
225229
{
226230
deferred_lookup_gates_.resize(num_threads);
227231
deferred_range_constraints_.resize(num_threads);
232+
deferred_non_native_field_muls_.resize(num_threads);
233+
}
234+
235+
/**
236+
* @brief Replay all deferred non-native field multiplications into the shared cache.
237+
*/
238+
void apply_deferred_non_native_field_muls()
239+
{
240+
for (auto& thread_buf : deferred_non_native_field_muls_) {
241+
for (auto& entry : thread_buf) {
242+
cached_partial_non_native_field_multiplications.emplace_back(entry);
243+
}
244+
thread_buf.clear();
245+
}
228246
}
229247

230248
/**
@@ -467,6 +485,7 @@ class UltraCircuitBuilder_ : public CircuitBuilderBase<typename ExecutionTrace_:
467485
// Replay deferred operations
468486
apply_deferred_lookup_gates();
469487
apply_deferred_range_constraints();
488+
apply_deferred_non_native_field_muls();
470489
{
471490
size_t total_deferred = 0;
472491
for (size_t t = 0; t < this->deferred_assert_equals_.size(); t++) {

0 commit comments

Comments
 (0)