pub const MINIMISE_BATCH_MIN_PROBLEMS: usize = 256;Expand description
Problem count below which a ComputeBackend::CpuMulti request runs
golden_section_batch on the calling thread instead.
§Measured crossover
Methodology. Measured 2026-08-13 on this workspace’s development machine,
std::thread::available_parallelism() = 4, release build, --features parallel, rayon’s global pool, otherwise-idle machine. Batches of n
independent problems (x - x0_i)^2 with the vertices x0_i spread over
[-3, 3) so per-lane iteration counts differ, bracket [-5, 5],
MinSettings::default, Sense::Minimise. Best of 7 samples per point,
reported as wall clock for one whole batch. Produced by the #[ignore]d
minimise_batch_crossover_benchmark test in minimise/tests.rs and
transcribed from its printed output. The cheap objective is the two-flop
parabola above; the costly objective adds a ln/exp/sqrt chain per
evaluation, standing in for an equation-of-state flash. The (repeat)
columns are the speed-ups from a second, independent run of the same
benchmark, carried alongside rather than averaged away because the parallel
column is far noisier than the serial one.
| Problems | cheap serial | cheap multi | speed-up | (repeat) | costly serial | costly multi | speed-up | (repeat) |
|---|---|---|---|---|---|---|---|---|
| 16 | 2.24 us | 10.06 us | 0.22x | 0.24x | 13.87 us | 12.94 us | 1.07x | 0.41x |
| 32 | 4.40 us | 29.98 us | 0.15x | 0.13x | 29.80 us | 44.04 us | 0.68x | 0.74x |
| 64 | 8.77 us | 31.47 us | 0.28x | 0.34x | 63.53 us | 64.86 us | 0.98x | 1.24x |
| 128 | 17.96 us | 36.40 us | 0.49x | 0.86x | 140.68 us | 73.43 us | 1.92x | 1.42x |
| 256 | 55.42 us | 49.41 us | 1.12x | 1.17x | 290.00 us | 186.77 us | 1.55x | 2.91x |
| 512 | 148.21 us | 85.96 us | 1.72x | 3.00x | 613.95 us | 360.42 us | 1.70x | 2.94x |
| 1 024 | 370.80 us | 213.96 us | 1.73x | 2.81x | 1255.20 us | 675.41 us | 1.86x | 2.82x |
| 4 096 | 1542.64 us | 466.86 us | 3.30x | 3.23x | 5120.51 us | 1711.31 us | 2.99x | 2.86x |
| 16 384 | 6260.28 us | 1964.94 us | 3.19x | 2.09x | 20732.41 us | 10689.59 us | 1.94x | 2.69x |
| 65 536 | 28254.43 us | 8464.29 us | 3.34x | 1.55x | 84607.33 us | 32110.15 us | 2.63x | 2.03x |
Result. 256 is the smallest size at which neither objective lost in either run — cheap 1.12x and 1.17x, costly 1.55x and 2.91x — and it is the value this constant takes. At 128 the cheap objective lost both runs (0.49x, 0.86x) while the costly one won both (1.92x, 1.42x), which is the expected shape: a more expensive objective crosses over earlier because there is more work per lane to amortise the same dispatch cost. The honest headline is therefore that the crossover depends on the caller’s objective, and this single number is set for the cheapest objective a caller is likely to pass, so that it is safe for both.
§Relationship to crate::compute::CPU_MULTI_MIN_WORK_ITEMS
That constant documents itself as an unmeasured placeholder and invites per-kernel overrides. This is that override for the batched golden section.
Interpretation. It lands on exactly the same value as
crate::math::parallel::ROOT_BATCH_MIN_PROBLEMS (256), 16x below the
crate-wide placeholder (4 096) and 512x below
crate::fields::parallel::FIELD_PARALLEL_CROSSOVER (131 072). Two kernels
agreeing is not a coincidence and is worth stating for whoever takes bead
op-yvj.4.7: both do tens of iterations of arithmetic per lane against a
handful of loaded bytes, so both are compute bound, where the field kernels do
one or two flops per element loaded and are memory-bandwidth bound. The
crossover tracks that distinction, not the algorithm.
§Limitations
One machine, four logical cores, one objective family, idle. Not measured on
Android/Termux hardware and not on a many-core server. As with
crate::math::parallel::ROOT_BATCH_MIN_PROBLEMS, the crossover moves with
the caller’s objective cost, so a caller that knows its own objective is
expensive is better off naming a ComputeBackend explicitly than trusting
a single number.
§Units
A count of independent minimisation problems, dimensionless.