Skip to content

Commit 5e9fe41

Browse files
authored
fix: pin wasm batch-MSM dispatch to baseline (avoid #480 wasmtime chonk regression) (#568)
1 parent 2b2051f commit 5e9fe41

2 files changed

Lines changed: 22 additions & 0 deletions

File tree

barretenberg/cpp/src/barretenberg/ecc/scalar_multiplication/pippenger_batched.hpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,11 +182,19 @@ void pippenger_round_parallel_batched(std::span<std::span<typename Curve::Scalar
182182
// footprint, which tracks the span. A sparse-but-wide MSM (few non-zeros, large domain) must stay
183183
// "large" — splitting by active count instead drops it into the concurrent pool and thrashes cache.
184184
const size_t pool_width = bb::get_num_cpus();
185+
#ifdef __wasm__
186+
// wasm runs every MSM single-threaded, so the split uses a fixed point-count bound rather than
187+
// MSM_MIN_PTS_PER_THREAD (SIZE_MAX here, which would classify every member as small). The loop
188+
// below tests `n < mt_threshold` and the intended classification is `n <= SMALL_MSM_BATCH_THRESHOLD`,
189+
// so the exclusive bound is one past it.
190+
const size_t mt_threshold = SMALL_MSM_BATCH_THRESHOLD + 1;
191+
#else
185192
// overflow-safe MSM_MIN_PTS_PER_THREAD * pool_width
186193
const size_t mt_threshold =
187194
(pool_width <= 1 || MSM_MIN_PTS_PER_THREAD > std::numeric_limits<size_t>::max() / pool_width)
188195
? std::numeric_limits<size_t>::max()
189196
: MSM_MIN_PTS_PER_THREAD * pool_width;
197+
#endif
190198
std::vector<size_t> small_members;
191199
std::vector<size_t> large_members;
192200
small_members.reserve(K);
@@ -228,6 +236,11 @@ void pippenger_round_parallel_batched(std::span<std::span<typename Curve::Scalar
228236
// - max n <= Σn / pool_width (n is the work proxy): with largest-first ordering (below) the
229237
// makespan is max(largest, Σn / pool_width), so a dominant member can't strand one worker.
230238
// - pool_width >= CONCURRENT_MIN_POOL_WIDTH: fewer threads make the win too small to justify.
239+
#ifdef __wasm__
240+
// wasm keeps large members on the sequential shared-arena dispatch: with single-threaded MSMs the
241+
// concurrent path's per-worker live arenas buy nothing over one reused arena.
242+
const bool large_members_concurrent = false;
243+
#else
231244
static constexpr size_t CONCURRENT_MIN_MEMBERS = 100;
232245
static constexpr size_t CONCURRENT_MIN_POOL_WIDTH = 4;
233246
size_t total_large_n = 0;
@@ -239,6 +252,7 @@ void pippenger_round_parallel_batched(std::span<std::span<typename Curve::Scalar
239252
const bool large_members_concurrent = pool_width >= CONCURRENT_MIN_POOL_WIDTH &&
240253
large_members.size() > CONCURRENT_MIN_MEMBERS &&
241254
max_large_n <= total_large_n / pool_width;
255+
#endif
242256

243257
// Shared dynamically-sized arena for the sequential (large-member) calls. Sized to
244258
// the max requirement across those members so each MSM_fast finds enough space; a

barretenberg/cpp/src/barretenberg/ecc/scalar_multiplication/scalar_multiplication_fast.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,14 @@ inline constexpr size_t MSM_MIN_PTS_PER_THREAD = SIZE_MAX;
190190
inline constexpr size_t MSM_MIN_PTS_PER_THREAD = 256;
191191
#endif
192192

193+
// Point-count bound for the batch driver's concurrent/sequential split on wasm. Intra-MSM work is
194+
// always single-threaded on wasm (MSM_MIN_PTS_PER_THREAD == SIZE_MAX), so the native split rule
195+
// `n < MSM_MIN_PTS_PER_THREAD * pool_width` would classify every member as small and route them all
196+
// through the concurrent pool, whose per-worker arena is sized to the largest member and caps the
197+
// worker count by memory budget. This finite bound keeps large members on the sequential shared-arena
198+
// path so the concurrent pool retains full worker width. Members at or below it dispatch one-per-worker.
199+
inline constexpr size_t SMALL_MSM_BATCH_THRESHOLD = size_t{ 1 } << 13;
200+
193201
// Per-MSM_fast arena sizer. Returns 0 for shapes that fall back to the Jacobian-fast path
194202
// (no affine arena). Mirrors the inline budget calc inside `pippenger_round_parallel`;
195203
// declared here so the test suite can exercise the same sizer.

0 commit comments

Comments
 (0)