PERF-2 P3 bench: per-level comparison of the device V-cycle's work vectors against the CPU's (vcycle_f32_work) to locate the disagreement
CI / Build (macos-latest) (push) Waiting to run
CI / Test (macos-latest) (push) Blocked by required conditions
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 (ubuntu-latest) (push) Failing after 5s
CI / Build CPU-Only (Explicit) (push) Failing after 5s
Documentation / Build API Documentation (push) Failing after 5s
CI / Format Check (push) Failing after 11s
CI / Clippy Check (push) Failing after 14s
Documentation / Build User Guide (push) Successful in 11s
Performance Benchmarks / Run Benchmarks (push) Successful in 22s

This commit is contained in:
Omar Sobh
2026-09-16 01:08:31 -05:00
parent cb1647c0ef
commit 06a60b5fed
3 changed files with 47 additions and 2 deletions
@@ -15,7 +15,7 @@ use cudarc::driver::{CudaContext, CudaSlice, LaunchConfig, PushKernelArg};
use cudarc::nvrtc::{CompileOptions, compile_ptx_with_opts};
use rtx_cfd::solvers::incompressible::{
LevelExport, MgSmoother, MultigridParameters, PoissonProblem, export_hierarchy,
vcycle_f32_reference,
vcycle_f32_reference, vcycle_f32_work,
};
use std::sync::Arc;
use std::time::Instant;
@@ -342,6 +342,33 @@ fn batched_device_vcycle_go_no_go() {
// Correctness at K = 1 (and every batch member at K > 1).
vcycle(&mut dev, &r_f32, &mut z_out);
if k == 1 {
// Level by level against the CPU's work vectors (march 0).
let work = vcycle_f32_work(&prob, &params, &r_host);
for (l, (b_ref, x_ref, r_ref)) in work.iter().enumerate() {
let n = dev[l].n;
let mut b = vec![0.0f32; n * k];
let mut x = vec![0.0f32; n * k];
let mut r = vec![0.0f32; n * k];
stream.memcpy_dtoh(&dev[l].b, &mut b).unwrap();
stream.memcpy_dtoh(&dev[l].x, &mut x).unwrap();
stream.memcpy_dtoh(&dev[l].r, &mut r).unwrap();
stream.synchronize().unwrap();
let cmp = |a: &[f32], c: &[f32]| {
let (mut worst, mut scale) = (0.0f32, 0.0f32);
for &idx in &levels[l].cells {
let i = idx as usize;
worst = worst.max((a[i] - c[i]).abs());
scale = scale.max(c[i].abs());
}
(worst, scale)
};
let (db, sb) = cmp(&b[..n], b_ref);
let (dx, sx) = cmp(&x[..n], x_ref);
let (dr, sr) = cmp(&r[..n], r_ref);
println!(" level {l} ({} cells): |Δb| {db:.3e} / {sb:.3e}, |Δx| {dx:.3e} / {sx:.3e}, |Δr| {dr:.3e} / {sr:.3e}", levels[l].cells.len());
}
}
let mut worst = 0.0_f64;
for m in 0..k {
for idx in 0..n0 {