Nothing in the workspace builds a rayon global pool, so every parallel phase runs on rayon's default, available_parallelism(). On Apple silicon that counts efficiency cores alongside performance ones. This machine reports six of each, so compute-bound work is spread across twelve threads that are not interchangeable.
That is the problem. Rayon hands every thread a roughly equal share, but a phase ends when its slowest thread ends. An efficiency core runs this kind of work at a fraction of a performance core's rate, so six shares finish quickly and six finish late, and the fast threads wait at every sumcheck round barrier.
We already depend on a helper that fixes it. flock_core::init_perf_thread_pool sizes the global pool to hw.perflevel0.physicalcpu and does nothing when RAYON_NUM_THREADS is set, so an explicit setting still wins. flock-core is pinned in the workspace manifest and already used by crates/pcs and crates/field. No crate of ours calls it.
What it could win: nothing waits on a straggler, so barrier-heavy phases stop paying for the slowest share. It costs nothing to try and is the smallest change on the list.
Two things to settle. The global pool is process-wide and can only be built once, so whether a library sets it or every binary and bench does is a policy call rather than a detail. And the prover and the verifier may not want the same size.
Effort S.
Nothing in the workspace builds a rayon global pool, so every parallel phase runs on rayon's default,
available_parallelism(). On Apple silicon that counts efficiency cores alongside performance ones. This machine reports six of each, so compute-bound work is spread across twelve threads that are not interchangeable.That is the problem. Rayon hands every thread a roughly equal share, but a phase ends when its slowest thread ends. An efficiency core runs this kind of work at a fraction of a performance core's rate, so six shares finish quickly and six finish late, and the fast threads wait at every sumcheck round barrier.
We already depend on a helper that fixes it.
flock_core::init_perf_thread_poolsizes the global pool tohw.perflevel0.physicalcpuand does nothing whenRAYON_NUM_THREADSis set, so an explicit setting still wins.flock-coreis pinned in the workspace manifest and already used bycrates/pcsandcrates/field. No crate of ours calls it.What it could win: nothing waits on a straggler, so barrier-heavy phases stop paying for the slowest share. It costs nothing to try and is the smallest change on the list.
Two things to settle. The global pool is process-wide and can only be built once, so whether a library sets it or every binary and bench does is a policy call rather than a detail. And the prover and the verifier may not want the same size.
Effort S.