64 std::array<uint16_t, MAX_SCHEDULE_WINDOWS>
bit_base{};
88 size_t num_logical_threads)
noexcept
90 constexpr uint32_t MAX_C = 20;
93 static_cast<void>(n_input);
94 static_cast<void>(num_logical_threads);
97 static constexpr uint64_t BAC_A = 4;
98 static constexpr uint64_t BAC_B = 12;
99 uint64_t best_cost =
static_cast<uint64_t
>(-1);
100 for (uint32_t window_bits = 2; window_bits < MAX_C; ++window_bits) {
101 const uint64_t rounds = (num_bits + 2 + window_bits - 1) / window_bits;
102 const uint64_t buckets = (uint64_t{ 1 } << (window_bits - 1)) + 1;
103 const uint64_t n = num_points;
104 const uint64_t cost = rounds * ((BAC_A * n) + (BAC_B * buckets));
105 if (cost < best_cost) {
121 size_t bits_remaining = num_bits + 2;
122 size_t bit_offset = 0;
126 sched.bit_base[w] =
static_cast<uint16_t
>(bit_offset);
127 sched.window_bits_per_window[w] =
static_cast<uint8_t
>(window_bits_w);
128 bit_offset += window_bits_w;
129 bits_remaining -= window_bits_w;
132 sched.num_windows = w;
199 size_t global_max_overflow_per_window,
201 size_t phase_a_cluster_members_cap,
202 size_t phase_a_cluster_offsets_cap,
203 size_t windows_per_batch,
204 size_t dense_stride_est)
noexcept
206 auto align_up = [](
size_t off,
size_t align) ->
size_t {
return (off + align - 1) & ~(align - 1); };
207 auto layout_add = [&](
size_t& off,
size_t bytes,
size_t align) { off = align_up(off, align) + bytes; };
212 layout_add(
ts_fixed_layout,
sizeof(uint32_t) * chunk_capacity,
alignof(uint32_t));
218 layout_add(
ts_fixed_layout,
sizeof(VecField) * pack_cap,
alignof(VecField));
221 layout_add(
ts_fixed_layout,
sizeof(uint32_t) * global_max_overflow_per_window,
alignof(uint32_t));
227 layout_add(
pa_layout,
sizeof(uint32_t) * phase_a_cluster_members_cap,
alignof(uint32_t));
228 layout_add(
pa_layout,
sizeof(uint32_t) * phase_a_cluster_offsets_cap,
alignof(uint32_t));
243 if (windows_per_batch != 0) {
244 const size_t dense_total = windows_per_batch * dense_stride_est;
245 const size_t dense_pair_max = dense_total / 2;
269 const size_t per_thread = (B_eff > 1) ? ((B_eff - 1 + num_threads - 1) / num_threads) :
size_t{ 1 };
277 return (B_eff > 0) ? (B_eff - 1 + num_threads - 1) :
size_t{ 0 };
283 size_t subchunk_entries_cap)
noexcept
285 const size_t global_max_chunk_len = (n + num_threads - 1) / num_threads;
286 return (global_max_chunk_len + subchunk_entries_cap - 1) / subchunk_entries_cap;
299template <
typename Curve>
301 size_t num_threads,
size_t B_eff,
size_t n,
size_t dense_stride,
size_t worker_total)
noexcept
304 const size_t hist_h_bytes_pw =
size_t{ 4 } * num_threads * B_eff;
305 const size_t hist_o_bytes_pw = (
sizeof(
ChunkOutput<Curve>) * num_threads) + (
size_t{ 96 } * num_threads);
306 const size_t hist_slot_bytes_pw =
std::max(hist_h_bytes_pw, hist_o_bytes_pw);
307 const size_t dense_slot_bytes_pw =
size_t{ 65 } * bucket_partials_max;
308 return (
size_t{ 4 } * n) + hist_slot_bytes_pw + dense_slot_bytes_pw + (
size_t{ 8 } * (B_eff + 1)) +
309 (
size_t{ 8 } * (num_threads + 1)) + (
size_t{ 8 } * (num_threads + 1)) + (
size_t{ 8 } * num_threads) +
310 (
size_t{ 8 } * num_threads) + (
size_t{ 8 } * num_threads) + (
size_t{ 16 } * worker_total) +
311 (
size_t{ 8 } * num_threads) + (
size_t{ 87 } * worker_total * dense_stride);
318 bool inline_glv_double,
319 size_t profile_threads)
noexcept
322 + (use_glv ?
size_t{ 32 } * n :
size_t{ 0 })
323 + (inline_glv_double ?
size_t{ 64 } * n :
size_t{ 0 })
324 + (profile_threads *
size_t{ 1024 });
342[[nodiscard]]
inline size_t solve_wpb(
size_t per_window_bytes,
size_t available_budget,
size_t W_R)
noexcept
347 if (per_window_bytes == 0 || available_budget == 0) {
350 return std::min(
std::max<size_t>(1, available_budget / per_window_bytes), W_R);
typename Group::element Element
typename Group::affine_element AffineElement
WindowSchedule build_window_schedule(size_t num_bits, size_t window_bits) noexcept
constexpr size_t BATCH_MEM_BUDGET
size_t compute_global_max_overflow_per_window(size_t n, size_t num_threads, size_t subchunk_entries_cap) noexcept
constexpr size_t BATCH_CAPACITY
constexpr size_t window_sums_storage_bytes() noexcept
constexpr size_t MIN_AFFINE_THREAD_RATIO
constexpr size_t DEDUP_MAX_CLUSTERS
constexpr size_t MIN_BATCH_CAPACITY
size_t compute_phase_one_prologue_bytes(size_t n, bool use_glv, bool inline_glv_double, size_t profile_threads) noexcept
size_t solve_wpb(size_t per_window_bytes, size_t available_budget, size_t W_R) noexcept
constexpr size_t GATHER_PREFETCH_DIST
constexpr size_t DEDUP_MAX_CHUNK_MEMBERS
constexpr size_t SUBCHUNK_ENTRIES_CAP
constexpr size_t DEDUP_MAX_MEMBERS
size_t compute_per_window_bytes(size_t num_threads, size_t B_eff, size_t n, size_t dense_stride, size_t worker_total) noexcept
size_t compute_bucket_partials_max(size_t B_eff, size_t num_threads) noexcept
PhaseACaps compute_phase_a_caps(size_t n, size_t num_threads) noexcept
size_t compute_dense_stride(size_t B_eff, size_t num_threads) noexcept
uint32_t choose_window_bits(size_t num_points, size_t num_bits, size_t n_input, size_t num_logical_threads) noexcept
constexpr size_t MAX_SCHEDULE_WINDOWS
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
static constexpr size_t PACKED_DRAIN_VECTORFIELD_RUNS
static constexpr size_t WORKER_SLAB_ALIGN
typename Curve::AffineElement AffineElement
size_t per_worker_union_bytes
static constexpr size_t PHASE_A_STAGED_CAP
size_t per_worker_per_wpb_layout
static constexpr size_t PHASE_A_BUCKET_REP_CAP
static constexpr size_t PHASE_A_DIRTY_SLOTS_CAP
static constexpr size_t PHASE_A_CHUNK_CAP
typename Curve::BaseField BaseField
PerWorkerArenaLayout(size_t chunk_capacity, size_t global_max_overflow_per_window, bool dedup_active, size_t phase_a_cluster_members_cap, size_t phase_a_cluster_offsets_cap, size_t windows_per_batch, size_t dense_stride_est) noexcept
std::array< uint8_t, MAX_SCHEDULE_WINDOWS > window_bits_per_window
std::array< uint16_t, MAX_SCHEDULE_WINDOWS > bit_base