isl: record where the threaded visibility sweep pays and where it does not

A single visibility test costs a few nanoseconds, so the thread start up is
only repaid by a large matrix. Measured on sixteen cores the parallel form
gains from a few hundred satellites and loses below that, so the note says
so and points a small shell at the sequential form.
This commit is contained in:
ApsisRS contributors 2026-09-30 18:39:10 +08:00
parent 9908d8e829
commit 1c5dddc229
1 changed files with 10 additions and 0 deletions

View File

@ -40,8 +40,18 @@ pub fn visibility_matrix(positions: &[Vec3], body_radius: f64) -> Vec<bool> {
/// same order. The pairs are independent, so splitting the flat index space /// same order. The pairs are independent, so splitting the flat index space
/// across threads needs no coordination and produces the same matrix however /// across threads needs no coordination and produces the same matrix however
/// the work is divided. /// the work is divided.
///
/// The gain from threading is modest here and shrinks as the matrix shrinks.
/// A single visibility test is a few nanoseconds, so the cost of starting the
/// threads is only repaid by a large matrix: on a sixteen core machine a few
/// hundred satellites already gain, while a few dozen lose. The sequential
/// form is the better choice for a small shell, and this one exists for the
/// large ones where the quadratic sweep dominates.
pub fn visibility_matrix_parallel(positions: &[Vec3], body_radius: f64) -> Vec<bool> { pub fn visibility_matrix_parallel(positions: &[Vec3], body_radius: f64) -> Vec<bool> {
let len = positions.len(); let len = positions.len();
// The pairs are independent, so splitting the flat index space across
// threads needs no coordination. `map_index` owns the output buffer,
// which is what lets the threads write disjoint slots of one allocation.
map_index(len * len, |index| { map_index(len * len, |index| {
let row = index / len; let row = index / len;
let column = index - row * len; let column = index - row * len;