PERF-2 P0-b: CG iterations per Poisson solve in the profile (ms per V-cycle) and sub-timers inside the patch regeneration (outline, hull + offset, ring projection, Winslow sweeps, respace, warm bookkeeping, mesh finalisation)
CI / Test (ubuntu-latest) (push) Blocked by required conditions
CI / Python Bindings (maturin) (macos-latest) (push) Blocked by required conditions
CI / Python Bindings (maturin) (ubuntu-latest) (push) Blocked by required conditions
CI / WASM Build + Size Check (push) Blocked by required conditions
CI / Distributed Training Tests (push) Blocked by required conditions
CI / CI Success (push) Blocked by required conditions
CI / Build (macos-latest) (push) Waiting to run
CI / Test (macos-latest) (push) Blocked by required conditions
Documentation / Build API Documentation (push) Failing after 5s
CI / Build (ubuntu-latest) (push) Failing after 6s
Documentation / Build User Guide (push) Successful in 6s
CI / Format Check (push) Failing after 14s
CI / Clippy Check (push) Failing after 48s
CI / Build CPU-Only (Explicit) (push) Failing after 2m21s
Performance Benchmarks / Run Benchmarks (push) Successful in 4m4s
CI / Test (ubuntu-latest) (push) Blocked by required conditions
CI / Python Bindings (maturin) (macos-latest) (push) Blocked by required conditions
CI / Python Bindings (maturin) (ubuntu-latest) (push) Blocked by required conditions
CI / WASM Build + Size Check (push) Blocked by required conditions
CI / Distributed Training Tests (push) Blocked by required conditions
CI / CI Success (push) Blocked by required conditions
CI / Build (macos-latest) (push) Waiting to run
CI / Test (macos-latest) (push) Blocked by required conditions
Documentation / Build API Documentation (push) Failing after 5s
CI / Build (ubuntu-latest) (push) Failing after 6s
Documentation / Build User Guide (push) Successful in 6s
CI / Format Check (push) Failing after 14s
CI / Clippy Check (push) Failing after 48s
CI / Build CPU-Only (Explicit) (push) Failing after 2m21s
Performance Benchmarks / Run Benchmarks (push) Successful in 4m4s
Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01YJPeT6WA2e7YvAnS875AHL
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
172a26dee4
commit
1547d14ff1
@@ -721,6 +721,23 @@ pub fn cylinder_flag_patch_deformed_tip(
|
|||||||
|
|
||||||
/// [`cylinder_flag_patch_deformed_from`] with the flat tip.
|
/// [`cylinder_flag_patch_deformed_from`] with the flat tip.
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
thread_local! {
|
||||||
|
/// PERF-2 P0 (`docs/perf2_campaign.md`): wall time [ns] of the
|
||||||
|
/// regeneration's stages on this thread — outline, hull + offset, ring
|
||||||
|
/// projection, Winslow sweeps, respace, warm bookkeeping, mesh
|
||||||
|
/// finalisation — and the number of builds (slot 7).
|
||||||
|
static REGEN_NS: std::cell::RefCell<[u64; 8]> = const { std::cell::RefCell::new([0; 8]) };
|
||||||
|
}
|
||||||
|
|
||||||
|
fn regen_charge(slot: usize, start: std::time::Instant) {
|
||||||
|
REGEN_NS.with(|r| r.borrow_mut()[slot] += start.elapsed().as_nanos() as u64);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The regeneration's stage times so far on this thread (see `REGEN_NS`).
|
||||||
|
pub fn regen_profile() -> [u64; 8] {
|
||||||
|
REGEN_NS.with(|r| *r.borrow())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn cylinder_flag_patch_deformed_from_tip(
|
pub fn cylinder_flag_patch_deformed_from_tip(
|
||||||
prev: Option<&PatchMesh>,
|
prev: Option<&PatchMesh>,
|
||||||
centre: [f64; 2],
|
centre: [f64; 2],
|
||||||
@@ -736,9 +753,11 @@ pub fn cylinder_flag_patch_deformed_from_tip(
|
|||||||
winslow_sweeps: usize,
|
winslow_sweeps: usize,
|
||||||
tip_corner: f64,
|
tip_corner: f64,
|
||||||
) -> CfdResult<(PatchMesh, (usize, f64))> {
|
) -> CfdResult<(PatchMesh, (usize, f64))> {
|
||||||
|
let t0 = std::time::Instant::now();
|
||||||
let (inner, tip) = cylinder_flag_outline_deformed_tip(
|
let (inner, tip) = cylinder_flag_outline_deformed_tip(
|
||||||
centre, r, t, edges, x_tip_ref, fillet, 3, 16, h, 1.15, tip_corner,
|
centre, r, t, edges, x_tip_ref, fillet, 3, 16, h, 1.15, tip_corner,
|
||||||
);
|
);
|
||||||
|
regen_charge(0, t0);
|
||||||
// With a flat tip the outline's corners would put 90° corners on the
|
// With a flat tip the outline's corners would put 90° corners on the
|
||||||
// hull, whose normal offset folds the rays at the tip; the tip disc
|
// hull, whose normal offset folds the rays at the tip; the tip disc
|
||||||
// (already a hull source) covers the tip, so the inner points ahead of
|
// (already a hull source) covers the tip, so the inner points ahead of
|
||||||
@@ -1087,8 +1106,11 @@ fn o_grid_from_outline(
|
|||||||
) -> CfdResult<(PatchMesh, (usize, f64))> {
|
) -> CfdResult<(PatchMesh, (usize, f64))> {
|
||||||
inner.reverse(); // clockwise
|
inner.reverse(); // clockwise
|
||||||
let ns = inner.len();
|
let ns = inner.len();
|
||||||
|
let t0 = std::time::Instant::now();
|
||||||
let hull = convex_hull(hull_src);
|
let hull = convex_hull(hull_src);
|
||||||
let outer_poly = offset_convex_polygon(&hull, offset, 24);
|
let outer_poly = offset_convex_polygon(&hull, offset, 24);
|
||||||
|
regen_charge(1, t0);
|
||||||
|
let t0 = std::time::Instant::now();
|
||||||
// Initial outer ring: the inner point pushed along its outward normal
|
// Initial outer ring: the inner point pushed along its outward normal
|
||||||
// (the ring is clockwise, so the outward normal is the LEFT-hand normal
|
// (the ring is clockwise, so the outward normal is the LEFT-hand normal
|
||||||
// of the direction of travel) and projected onto the hull offset —
|
// of the direction of travel) and projected onto the hull offset —
|
||||||
@@ -1109,6 +1131,7 @@ fn o_grid_from_outline(
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
regen_charge(2, t0);
|
||||||
let mut inner_closed = inner.clone();
|
let mut inner_closed = inner.clone();
|
||||||
inner_closed.push(inner[0]);
|
inner_closed.push(inner[0]);
|
||||||
// Transfinite start, or the previous mesh's interior with the new
|
// Transfinite start, or the previous mesh's interior with the new
|
||||||
@@ -1153,15 +1176,23 @@ fn o_grid_from_outline(
|
|||||||
let mut last = f64::INFINITY;
|
let mut last = f64::INFINITY;
|
||||||
let mut done = 0;
|
let mut done = 0;
|
||||||
for k in 0..winslow_sweeps {
|
for k in 0..winslow_sweeps {
|
||||||
|
let t0 = std::time::Instant::now();
|
||||||
let before = x.clone();
|
let before = x.clone();
|
||||||
|
regen_charge(5, t0);
|
||||||
|
let t0 = std::time::Instant::now();
|
||||||
winslow_smooth(&mut x, ns, 0.0, 1, Some(&outer_poly));
|
winslow_smooth(&mut x, ns, 0.0, 1, Some(&outer_poly));
|
||||||
|
regen_charge(3, t0);
|
||||||
|
let t0 = std::time::Instant::now();
|
||||||
respace_rays(&mut x, ns, &eta);
|
respace_rays(&mut x, ns, &eta);
|
||||||
|
regen_charge(4, t0);
|
||||||
|
let t0 = std::time::Instant::now();
|
||||||
last = x
|
last = x
|
||||||
.iter()
|
.iter()
|
||||||
.zip(&before)
|
.zip(&before)
|
||||||
.flat_map(|(r, b)| r.iter().zip(b))
|
.flat_map(|(r, b)| r.iter().zip(b))
|
||||||
.map(|(p, q)| ((p[0] - q[0]).powi(2) + (p[1] - q[1]).powi(2)).sqrt())
|
.map(|(p, q)| ((p[0] - q[0]).powi(2) + (p[1] - q[1]).powi(2)).sqrt())
|
||||||
.fold(0.0, f64::max);
|
.fold(0.0, f64::max);
|
||||||
|
regen_charge(5, t0);
|
||||||
done = k + 1;
|
done = k + 1;
|
||||||
if last < 1e-10 * h {
|
if last < 1e-10 * h {
|
||||||
break;
|
break;
|
||||||
@@ -1169,10 +1200,15 @@ fn o_grid_from_outline(
|
|||||||
}
|
}
|
||||||
(done, last)
|
(done, last)
|
||||||
} else {
|
} else {
|
||||||
|
let t0 = std::time::Instant::now();
|
||||||
let report = winslow_smooth(&mut x, ns, 1e-10 * h, winslow_sweeps, Some(&outer_poly));
|
let report = winslow_smooth(&mut x, ns, 1e-10 * h, winslow_sweeps, Some(&outer_poly));
|
||||||
|
regen_charge(3, t0);
|
||||||
|
let t0 = std::time::Instant::now();
|
||||||
respace_rays(&mut x, ns, &eta);
|
respace_rays(&mut x, ns, &eta);
|
||||||
|
regen_charge(4, t0);
|
||||||
report
|
report
|
||||||
};
|
};
|
||||||
|
let t0 = std::time::Instant::now();
|
||||||
let mut xs = Vec::with_capacity((nn + 1) * (ns + 1));
|
let mut xs = Vec::with_capacity((nn + 1) * (ns + 1));
|
||||||
let mut ys = Vec::with_capacity(xs.capacity());
|
let mut ys = Vec::with_capacity(xs.capacity());
|
||||||
for row in &x {
|
for row in &x {
|
||||||
@@ -1182,5 +1218,7 @@ fn o_grid_from_outline(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mesh = PatchMesh::from_nodes(ns, nn, xs, ys, Some([0.0, 0.0]))?;
|
let mesh = PatchMesh::from_nodes(ns, nn, xs, ys, Some([0.0, 0.0]))?;
|
||||||
|
regen_charge(6, t0);
|
||||||
|
REGEN_NS.with(|r| r.borrow_mut()[7] += 1);
|
||||||
Ok((mesh, report))
|
Ok((mesh, report))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -168,9 +168,9 @@ pub struct EmbeddedPisoSolver {
|
|||||||
/// (measured: at 1e-2 the first corrector's rounds never settled below
|
/// (measured: at 1e-2 the first corrector's rounds never settled below
|
||||||
/// a 1e-3 relative change — 20/20 rounds every step).
|
/// a 1e-3 relative change — 20/20 rounds every step).
|
||||||
inner_stop_factor: f64,
|
inner_stop_factor: f64,
|
||||||
/// PERF-2 P0: Poisson `(setup ns, iterate ns, calls)` summed over
|
/// PERF-2 P0: Poisson `(setup ns, iterate ns, calls, CG iterations)`
|
||||||
/// every multigrid-PCG solve (`docs/perf2_campaign.md`).
|
/// summed over every multigrid-PCG solve (`docs/perf2_campaign.md`).
|
||||||
poisson_profile: std::cell::Cell<(u64, u64, u64)>,
|
poisson_profile: std::cell::Cell<(u64, u64, u64, u64)>,
|
||||||
moving: bool,
|
moving: bool,
|
||||||
/// Mask hysteresis band in multiples of the min cell size (0 = off).
|
/// Mask hysteresis band in multiples of the min cell size (0 = off).
|
||||||
mask_hysteresis: f64,
|
mask_hysteresis: f64,
|
||||||
@@ -197,7 +197,7 @@ impl EmbeddedPisoSolver {
|
|||||||
fringe: None,
|
fringe: None,
|
||||||
fringe_correction: Vec::new(),
|
fringe_correction: Vec::new(),
|
||||||
inner_stop_factor: 1e-2,
|
inner_stop_factor: 1e-2,
|
||||||
poisson_profile: std::cell::Cell::new((0, 0, 0)),
|
poisson_profile: std::cell::Cell::new((0, 0, 0, 0)),
|
||||||
moving: false,
|
moving: false,
|
||||||
mask_hysteresis: 0.0,
|
mask_hysteresis: 0.0,
|
||||||
time: 0.0,
|
time: 0.0,
|
||||||
@@ -294,8 +294,8 @@ impl EmbeddedPisoSolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Relative part of the pressure solve's inner stop (see the field).
|
/// Relative part of the pressure solve's inner stop (see the field).
|
||||||
/// The Poisson solves' `(setup ns, iterate ns, calls)` so far.
|
/// The Poisson solves' `(setup ns, iterate ns, calls, CG iterations)` so far.
|
||||||
pub fn poisson_profile(&self) -> (u64, u64, u64) {
|
pub fn poisson_profile(&self) -> (u64, u64, u64, u64) {
|
||||||
self.poisson_profile.get()
|
self.poisson_profile.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -304,9 +304,13 @@ impl EmbeddedPisoSolver {
|
|||||||
inner_stop,
|
inner_stop,
|
||||||
anchor_cell,
|
anchor_cell,
|
||||||
);
|
);
|
||||||
let (s0, i0, c0) = self.poisson_profile.get();
|
let (s0, i0, c0, k0) = self.poisson_profile.get();
|
||||||
self.poisson_profile
|
self.poisson_profile.set((
|
||||||
.set((s0 + solution.setup_ns, i0 + solution.iterate_ns, c0 + 1));
|
s0 + solution.setup_ns,
|
||||||
|
i0 + solution.iterate_ns,
|
||||||
|
c0 + 1,
|
||||||
|
k0 + solution.iterations as u64,
|
||||||
|
));
|
||||||
// Unconverged: fall back to the SOR sweeps for this projection
|
// Unconverged: fall back to the SOR sweeps for this projection
|
||||||
// rather than apply a correction that did not reach the stop.
|
// rather than apply a correction that did not reach the stop.
|
||||||
multigrid_converged = solution.converged;
|
multigrid_converged = solution.converged;
|
||||||
|
|||||||
@@ -1164,12 +1164,14 @@ impl OversetFluid {
|
|||||||
/// setup / iterate split.
|
/// setup / iterate split.
|
||||||
pub fn profile_line(&self) -> Option<String> {
|
pub fn profile_line(&self) -> Option<String> {
|
||||||
let t = self.solver.timers()?;
|
let t = self.solver.timers()?;
|
||||||
let (ps, pi, pc) = self.solver.background().poisson_profile();
|
let (ps, pi, pc, pk) = self.solver.background().poisson_profile();
|
||||||
|
let rg = rtx_cfd::mesh::patch_gen::regen_profile();
|
||||||
let s = |ns: u64| ns as f64 * 1e-9;
|
let s = |ns: u64| ns as f64 * 1e-9;
|
||||||
let adv = s(t.advance_ns).max(1e-300);
|
let adv = s(t.advance_ns).max(1e-300);
|
||||||
let pct = |ns: u64| 100.0 * s(ns) / adv;
|
let pct = |ns: u64| 100.0 * s(ns) / adv;
|
||||||
Some(format!(
|
Some(
|
||||||
" advance split over {} steps ({} rounds), {:.0} s: overlap build {:.0} s ({:.1}%), predictor bg {:.0} s ({:.1}%), predictor patch {:.0} s ({:.1}%), bg Poisson {:.0} s ({:.1}%) [setup {:.0} s, iterate {:.0} s, {} solves], patch BiCGSTAB {:.0} s ({:.1}%), round exchange {:.0} s ({:.1}%), apply {:.0} s ({:.1}%), end exchange {:.0} s ({:.1}%), other {:.0} s",
|
format!(
|
||||||
|
" advance split over {} steps ({} rounds), {:.0} s: overlap build {:.0} s ({:.1}%), predictor bg {:.0} s ({:.1}%), predictor patch {:.0} s ({:.1}%), bg Poisson {:.0} s ({:.1}%) [setup {:.0} s, iterate {:.0} s, {} solves, {} CG iterations, {:.2} ms per V-cycle], patch BiCGSTAB {:.0} s ({:.1}%), round exchange {:.0} s ({:.1}%), apply {:.0} s ({:.1}%), end exchange {:.0} s ({:.1}%), other {:.0} s",
|
||||||
t.steps,
|
t.steps,
|
||||||
t.rounds,
|
t.rounds,
|
||||||
adv,
|
adv,
|
||||||
@@ -1184,6 +1186,8 @@ impl OversetFluid {
|
|||||||
s(ps),
|
s(ps),
|
||||||
s(pi),
|
s(pi),
|
||||||
pc,
|
pc,
|
||||||
|
pk,
|
||||||
|
1e3 * s(pi) / (pk + pc).max(1) as f64,
|
||||||
s(t.patch_solve_ns),
|
s(t.patch_solve_ns),
|
||||||
pct(t.patch_solve_ns),
|
pct(t.patch_solve_ns),
|
||||||
s(t.round_exchange_ns),
|
s(t.round_exchange_ns),
|
||||||
@@ -1200,7 +1204,18 @@ impl OversetFluid {
|
|||||||
+ t.round_exchange_ns
|
+ t.round_exchange_ns
|
||||||
+ t.apply_ns
|
+ t.apply_ns
|
||||||
+ t.end_exchange_ns),
|
+ t.end_exchange_ns),
|
||||||
))
|
) + &format!(
|
||||||
|
"\n regeneration split ({} builds): outline {:.0} s, hull + offset {:.0} s, ring projection {:.0} s, Winslow sweeps {:.0} s, respace {:.0} s, warm bookkeeping {:.0} s, mesh finalisation {:.0} s",
|
||||||
|
rg[7],
|
||||||
|
s(rg[0]),
|
||||||
|
s(rg[1]),
|
||||||
|
s(rg[2]),
|
||||||
|
s(rg[3]),
|
||||||
|
s(rg[4]),
|
||||||
|
s(rg[5]),
|
||||||
|
s(rg[6])
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn time(&self) -> f64 {
|
pub fn time(&self) -> f64 {
|
||||||
|
|||||||
Reference in New Issue
Block a user