Skip to main content

Module par

Module par 

Source
Expand description

Minimal data-parallel primitives over std::thread::scope (no external deps). The thread count comes from FFDP_THREADS (if set) else available cores; threads <= 1 falls back to a plain sequential map, so behaviour is deterministic regardless of parallelism.

Two cost-control knobs keep parallelism a net win across problem sizes:

  • MIN_PAR: rounds with fewer than this many items run SERIALLY, so a tiny frontier (the common case on small problems, and the tail of large ones) never pays thread-spawn cost. Output is identical either way.
  • MAX_DEFAULT_THREADS: the auto thread count is capped, because measured scaling plateaus by ~4 cores (Amdahl: serial successor-gen/dedup/heap); spawning one thread per core per round past that is pure overhead. An explicit FFDP_THREADS is honoured uncapped.

Constants§

MIN_PAR
Below this item count a round runs serially (spawning isn’t worth it).

Functions§

num_threads
Resolve the worker count: FFDP_THREADS env override (uncapped), else min(cores, MAX_DEFAULT_THREADS).
par_map
Map f over items across threads scoped workers, preserving input order. Each worker owns a contiguous chunk; results are concatenated in order, so the output is identical to a sequential map (only the cost is parallel).
par_map_with
Like par_map, but each worker first builds a private state via init (e.g. reusable scratch buffers) and threads it through f, so per-item allocation is amortised across a chunk. Output order matches input.