Performance
Headline numbers by platform and workload, measured against vendor
libraries. Gap = Sonium ÷ vendor, so 1.00× is parity and cells marked
not measured are honest gaps — not parity claims. The full
living report is PERF.md in the repo; the iterative
dataset is ITERATIVE_PERF.json. Tables below are
generated from perf/*.md by
website/scripts/generate_perf_data.py — each section
names its source.
Apple M1
8 cores, macOS · vendor refs: Accelerate, SuperLU · criterion medians, rustc 1.99.0 · measured 2026-10-15 @ 39fde79e
Dense BLAS
GEMM vs Accelerate: parity on square NN (0.97–1.03×) with wins on thin shapes (0.64–0.89×); GEMV wins big (down to 0.03×). BLAS-1 is mixed — nrm2 wins everywhere (0.29–0.50×), real axpy/dot/scal trail at large n (up to 3.5×).
| Shape | f32 | f64 | Reading |
|---|---|---|---|
| sq 64/256/1024 NN | 1.00–1.03× | 0.97–1.00× | parity-or-better |
| thin 2048x128x2048 | 0.89× | 0.64× | we win |
| gemv, all shapes | 0.03–0.79× | 0.09–0.72× | we win big |
| nrm2, all n | 0.36–0.50× | 0.29–0.50× | we win |
| axpy/dot/scal real, large n | 1.28–3.48× | 0.98–2.29× | open: serial kernels |
perf/m1-blas.md · measured 2026-10-15 @ 39fde79e
Dense LAPACK
Factorization kernels vs Accelerate (lapack_compare). QR median 1.7×; Cholesky 5.04×/2.32× at 512/1024; LU dgetrf 1.36–2.39×. Full size sweep in perf/m1-lapack.md.
| Workload | Size | Sonium | Accelerate | Gap |
|---|---|---|---|---|
| Cholesky dpotrf | 2048 | 41.410 ms | 15.436 ms | 2.68× |
| Cholesky dpotrf | 4096 | 298.598 ms | 141.331 ms | 2.11× |
| LU dgetrf | 2048 | 70.679 ms | 51.922 ms | 1.36× |
| LU dgetrf | 4096 | 764.924 ms | 320.200 ms | 2.39× |
| LU sgetrf | 2048 | 28.757 ms | 44.173 ms | 0.65× |
| QR dgeqrf | 2048 | 665.609 ms | 357.880 ms | 1.86× |
| QR dgeqrf | 4096 | 6.344 s | 2.446 s | 2.59× |
perf/m1-lapack.md · measured 2026-10-15 @ 39fde79e
FFT
Not measured on M1: no perf/m1-fft.md dataset exists. Rerun the FFT cells on the M1 host (just perf-m1) to fill this section.
Sparse matrix
CSR SpMV roofline preflight (f32, prebaked): 75.42 µs, 7.8 GB/s effective. Effective bandwidth inside a CG+AMG Poisson 2-D solve (f64, self-reported — bytes moved ÷ solve time, so solver overhead is included; no vendor comparison).
| n | Solve | Iterations | Residual | Eff. SpMV BW |
|---|---|---|---|---|
| 961 | 0.41 ms | 12 | 8.5e-07 | 2.86 GB/s |
| 10,000 | 4.62 ms | 14 | 5.2e-07 | 3.13 GB/s |
| 99,856 | 72.98 ms | 18 | 6.7e-07 | 2.56 GB/s |
perf/m1-sparse-matrix.md · measured 2026-10-15 @ 39fde79e
Dense solvers
Blocked LU, one factorization + one solve per timing, vs Accelerate. Mid sizes trail 1.8–2.8×.
| N | Sonium | Accelerate | Gap | Residual |
|---|---|---|---|---|
| 64 | 0.113 ms | 0.052 ms | 2.17× | 8.71e-16 |
| 128 | 0.423 ms | 0.152 ms | 2.78× | 1.22e-15 |
| 256 | 1.788 ms | 0.863 ms | 2.07× | 1.66e-15 |
| 512 | 3.791 ms | 2.168 ms | 1.75× | 3.21e-15 |
perf/m1-dense-solvers.md · measured 2026-10-15 @ 39fde79e
Sparse solvers + preconditioners
Sparse direct vs SuperLU: not measured on M1 (the SuperLU column is unmeasured in perf/m1-sparse-solvers.md). Simplicial/Supernodal absolute times are in the dataset; rerun with SuperLU to fill this comparison.
CG + AMG on Poisson 2-D (f64): iterations stay nearly flat (12 → 18) over a 100× size range — the signature of an effective multigrid preconditioner.
| n | Solve | Iterations | Residual |
|---|---|---|---|
| 961 | 0.41 ms | 12 | 8.5e-07 |
| 10,000 | 4.62 ms | 14 | 5.2e-07 |
| 99,856 | 72.98 ms | 18 | 6.7e-07 |
Full dataset: 62 runs over 12 solver/preconditioner pairs (GMRES, FGMRES, CG, BiCGSTAB, IDR(s) × none/Jacobi/ILU/ILUT/AMG) on 5 matrices (Poisson, Helmholtz, 3-D Laplacian, anisotropic diffusion, saddle-point) — see perf/m1-sparse-solvers.md and ITERATIVE_PERF.json.
perf/m1-sparse-solvers.md · measured 2026-10-15 @ 39fde79e
Apple M4 Pro
14 cores, macOS · vendor refs: Accelerate, SuperLU · criterion medians, rustc 1.99.0 · measured 2026-10-07 → 10-15 @ 3e449331
Dense BLAS
GEMM vs Accelerate: parity-or-better on square NN up to 1024 and thin shapes; GEMV wins big across the board. BLAS-1 is mixed — nrm2 wins everywhere, real axpy/dot/scal trail at large n.
| Shape | f32 | f64 | Reading |
|---|---|---|---|
| sq 64/256/1024 NN | 0.96–1.10× | 0.93–1.01× | parity-or-better |
| thin 2048x128x2048 | 0.32× | 0.69× | we win |
| gemv, all shapes | 0.03–0.52× | 0.06–0.66× | we win big |
| nrm2, all n | 0.30–0.52× | 0.29–0.58× | we win |
| axpy/dot/scal real, large n | 3.33–7.79× | 3.39–6.02× | open: serial kernels |
perf/m4-blas.md · measured 2026-10-07 @ 3e449331
Dense LAPACK
Factorization kernels vs Accelerate (lapack_compare). QR is a steady ~1.5×; Cholesky reaches parity past N=2048 after a small-N dispatch pathology (potrf_f64 24.5×/15.69× at 512/1024); LU dgetrf is the open gap at 3.16–7.53×. Full size sweep in perf/m4-lapack.md.
| Workload | Size | Sonium | Accelerate | Gap |
|---|---|---|---|---|
| Cholesky dpotrf | 2048 | 23.632 ms | 19.055 ms | 1.24× |
| Cholesky dpotrf | 4096 | 141.269 ms | 119.643 ms | 1.18× |
| LU dgetrf | 2048 | 234.660 ms | 50.370 ms | 4.66× |
| LU dgetrf | 4096 | 781.804 ms | 247.696 ms | 3.16× |
| LU sgetrf | 2048 | 23.110 ms | 40.650 ms | 0.57× |
| QR dgeqrf | 2048 | 215.277 ms | 148.843 ms | 1.45× |
| QR dgeqrf | 4096 | 1.626 s | 1.043 s | 1.56× |
perf/m4-lapack.md · measured 2026-10-07 @ 3e449331
FFT
Single forward complex/real FFTs (f32/f64) vs Accelerate vDSP DFT. Audio band 512–4096 points, large band 1–4M points; cells are gap ranges over the sizes in each band (gap = Sonium ÷ Accelerate). Full size sweep in perf/m4-fft.md.
| Transform | Audio 512–4096 | Large 1–4M |
|---|---|---|
| complex f64 | — | — |
| complex f32 | — | — |
| real f64 | — | — |
| real f32 | — | — |
perf/m4-fft.md (Seeded 2026-10-15 (not yet measured; regenerate with just perf-cell m4 fft))
Sparse matrix
CSR SpMV roofline preflight (f32, prebaked): 112.18 µs, 5.3 GB/s effective. Effective bandwidth inside a CG+AMG Poisson 2-D solve (f64, self-reported — bytes moved ÷ solve time, so solver overhead is included; no vendor comparison).
| n | Solve | Iterations | Residual | Eff. SpMV BW |
|---|---|---|---|---|
| 961 | 0.41 ms | 12 | 8.5e-07 | 2.88 GB/s |
| 10,000 | 3.61 ms | 14 | 5.2e-07 | 4.01 GB/s |
| 99,856 | 72.86 ms | 18 | 6.6e-07 | 2.56 GB/s |
perf/m4-sparse-matrix.md · measured 2026-10-07 @ 3e449331
Dense solvers
Blocked LU, one factorization + one solve per timing, vs Accelerate. Down from 15–27× in the August small-N dataset; mid sizes still trail 1.9–4.6×.
| N | Sonium | Accelerate | Gap | Residual |
|---|---|---|---|---|
| 64 | 0.027 ms | 0.014 ms | 1.91× | 8.71e-16 |
| 128 | 0.262 ms | 0.057 ms | 4.56× | 1.22e-15 |
| 256 | 1.003 ms | 0.307 ms | 3.27× | 1.77e-15 |
| 512 | 2.989 ms | 1.612 ms | 1.85× | 2.87e-15 |
perf/m4-dense-solvers.md · measured 2026-10-07 @ 3e449331
Sparse solvers + preconditioners
Sparse direct vs SuperLU 7 (conv-diff grids, 1e-10 residual gate). Simplicial sits at 1.3–1.8× — down from 28–45× in August; supernodal trails at 2.5–3.9×.
| Grid | N | Simplicial / SLU | Supernodal / SLU |
|---|---|---|---|
| 8×8 | 64 | 1.34× | 2.49× |
| 12×12 | 144 | 1.49× | 2.74× |
| 16×16 | 256 | 1.64× | 3.86× |
| 20×20 | 400 | 1.78× | 3.07× |
| 28×28 | 784 | 1.72× | 3.00× |
CG + AMG on Poisson 2-D (f64): iterations stay nearly flat (12 → 18) over a 100× size range — the signature of an effective multigrid preconditioner.
| n | Solve | Iterations | Residual |
|---|---|---|---|
| 961 | 0.41 ms | 12 | 8.5e-07 |
| 10,000 | 3.61 ms | 14 | 5.2e-07 |
| 99,856 | 72.86 ms | 18 | 6.6e-07 |
Full dataset: 62 runs over 12 solver/preconditioner pairs (GMRES, FGMRES, CG, BiCGSTAB, IDR(s) × none/Jacobi/ILU/ILUT/AMG) on 5 matrices (Poisson, Helmholtz, 3-D Laplacian, anisotropic diffusion, saddle-point) — see perf/m4-sparse-solvers.md and ITERATIVE_PERF.json.
perf/m4-sparse-solvers.md · measured 2026-10-07 @ 3e449331
x86-64 — Threadripper PRO 3995WX
128 logical CPUs, Linux, rustc 1.98.1 · vendor refs: OpenBLAS (pthread, tuned threads), SuperLU, UMFPACK, CHOLMOD, PETSc · interleaved same-process A/B, median-of-reps, Sonium at 16 threads · measured 2026-09-27 → 10-15
Dense BLAS
GEMM vs OpenBLAS, hot medians, best-vs-best @32T (2026-09-27). Parity-or-better on square NN up to 1024 and thin shapes; trans-A and 2048 MT scaling are the open gaps.
| Shape | f32 | f64 | Reading |
|---|---|---|---|
| sq 256/512/1024 NN | 0.8–1.05× | 0.5–1.0× | parity-or-better |
| sq 2048 NN | 1.26× | 1.38× | open: MT scaling |
| thin NN (bemski / lu-sch) | 0.3–0.8× | 0.3–0.8× | we win big |
| trans-A (lu-tn) | 1.35–1.5× | 1.36–1.66× | open: structural |
| single-thread, all NN | ~1.0–1.1× | ~1.0× | parity |
GEMV vs OpenBLAS (first look, contended box — magnitudes only): NoTrans single-thread 1.1–1.6×, Trans single-thread 1.8–3.7× (serial kernel gap), Trans multi-thread large sizes ~parity.
Best-vs-best worklog 2026-09-27 — see root PERF.md
Dense LAPACK
Factorizations vs OpenBLAS LAPACK, criterion medians, residual-gated at 1e-10 (2026-10-01). Full size sweep in perf/x86-lapack.md.
| Workload | Size | Sonium | Vendor | Gap |
|---|---|---|---|---|
| Cholesky dpotrf | 2048 | 19.86 ms | 14.68 ms | 1.35× |
| Cholesky dpotrf | 4096 | 93.53 ms | 69.67 ms | 1.34× |
| Cholesky spotrf | 2048 | 8.75 ms | 7.18 ms | 1.22× |
| LU dgetrf | 2048 | 40.92 ms | 29.02 ms | 1.41× |
| LU dgetrf | 4096 | 272.04 ms | 132.66 ms | 2.05× |
| LU sgetrf | 2048 | 25.15 ms | 16.17 ms | 1.55× |
| QR dgeqrf+dorgqr | 2048 | 323.17 ms | 249.40 ms | 1.30× |
| QR dgeqrf+dorgqr | 4096 | 1578.56 ms | 1433.44 ms | 1.10× |
Criterion medians, residual-gated at 1e-10 (2026-10-01) — curated snapshot; see perf/x86-lapack.md for the refresh cells
FFT
Single forward complex/real FFTs (f32/f64) vs rustfft (complex) and realfft (real). Audio band 512–4096 points, large band 1–4M points; cells are gap ranges over the sizes in each band (gap = Sonium ÷ rustfft). Full size sweep in perf/x86-fft.md.
| Transform | Audio 512–4096 | Large 1–4M |
|---|---|---|
| complex f64 | 1.09–2.03× | 1.40–1.60× |
| complex f32 | 0.83–1.33× | 1.52–1.84× |
| real f64 | 0.95–1.24× | 1.45–1.88× |
| real f32 | 0.76–1.02× | 0.95–1.73× |
perf/x86-fft.md · measured 2026-10-15 @ ca156e4f
Sparse matrix
CSR SpMV roofline preflight (f32, prebaked): 111.26 µs, 5.3 GB/s effective (2026-10-01). No CPU vendor A/B yet — GPU SpMV/SpMM parity numbers are under CUDA.
| n | Solve | Iterations | Residual | Eff. SpMV BW |
|---|---|---|---|---|
| 961 | 0.57 ms | 12 | 8.5e-07 | 2.05 GB/s |
| 10,000 | 6.82 ms | 14 | 5.2e-07 | 2.12 GB/s |
| 99,856 | 95.15 ms | 18 | 6.7e-07 | 1.96 GB/s |
perf/x86-sparse-matrix.md · measured 2026-10-01 @ 47d8c891
Dense solvers
End-to-end factor+solve. dgetrf-1024 in-place passes the project's ≤1.2× gate (2026-09-27); dgetrf-2048 at 1.44× needs panel/Schur work.
| Workload | Sonium | OpenBLAS | Gap | Gate |
|---|---|---|---|---|
| LU dgetrf-1024, in-place | 8.67–9.06 ms | 7.42 ms | 1.17× | ≤1.2× PASS |
| LU dgetrf-2048 | — | — | 1.44× | FAIL |
perf/x86-dense-solvers.md (Seeded 2026-10-01 from root PERF.md D3 records (Threadripper PRO 3995WX, 2026-09-26 → 27))
Sparse solvers + preconditioners
Sparse direct vs SuperLU, interleaved rep-trajectory A/B with a 1e-10 residual gate (2026-09-28). Supernodal crosses over simplicial past n≈1600; the remaining gap is serial factor throughput.
| Cell | n | Simplicial / SLU | Supernodal / SLU |
|---|---|---|---|
| 32² conv-diff | 1024 | 1.68× | 2.15× |
| 40² conv-diff | 1600 | 1.82× | 2.12× |
| 128² conv-diff | 16384 | 3.7× | 1.8× |
| 128² Laplacian | 16384 | 3.8× | 1.9× |
Sparse Cholesky (5-pt Laplacian, n=16384) vs CHOLMOD: numeric factor 0.77× (faster), analyze ~8× (ordering gap), total 2.0×.
Sonium vs PETSc KSP, f64, largest sizes (2026-10-01, 108 runs, harness validation 37/43 — full table in perf/x86-sparse-solvers.md). AMG-preconditioned pairs are near parity; unpreconditioned GMRES rows compare different restart lengths and truncation, not solver quality.
| Solver + precond | Matrix | n | Sonium | PETSc | Gap |
|---|---|---|---|---|---|
| FGMRES + AMG | Poisson 2-D | 99,856 | 105.11 ms | 99.78 ms | 1.05× |
| CG + AMG | Poisson 2-D | 99,856 | 92.99 ms | 72.15 ms | 1.29× |
| CG + AMG | Laplacian 3-D | 97,336 | 111.13 ms | 75.44 ms | 1.47× |
| CG + AMG | aniso. diffusion | 99,856 | 56.70 ms | 35.74 ms | 1.59× |
| GMRES + ILU | saddle point | 99,372 | 132.17 ms | 88.54 ms | 1.49× |
| CG + Jacobi | Laplacian 3-D | 97,336 | 321.11 ms | 116.26 ms | 2.76× |
perf/x86-sparse-solvers.md · measured 2026-10-01 @ 47d8c891; sparse-direct + Cholesky rows: interleaved A/B 2026-09-28, see PERF.md
CUDA — RTX PRO 6000 Blackwell
Driver 610.57, idle GPU · vendor refs: cuBLAS, cuSPARSE, cuSOLVER · solver loops use persistent device handles (PersistentDeviceCsr / PrebakedSpmv) · measured 2026-09-26 → 10-15 @ 47d8c891
Dense BLAS
Bitwise-verified parity with cuBLAS across sizes 1024/2048/4096.
| Workload | Gap vs cuBLAS | Correctness |
|---|---|---|
| dgemm | 1.000× | bitwise |
| sgemm | 1.001× | bitwise |
| dgemv | 0.994× | bitwise |
| sgemv | 1.008× | bitwise |
perf/cuda-blas.md (Seeded 2026-10-01 from root PERF.md compute-202609 worklog (idle RTX PRO 6000, 2026-09-27))
Dense LAPACK
One-shot getrf_f64 kernel A/B incl. host→device upload (2026-10-01): we win while upload dominates, cuSOLVER past the 2048 → 4096 crossover. Solver loops use the persistent prebaked path (delegation row) at parity.
| Workload | Size | Sonium | cuSOLVER | Gap |
|---|---|---|---|---|
| LU dgetrf, one-shot | 512 | 2.837 ms | 5.622 ms | 0.50× |
| LU dgetrf, one-shot | 1024 | 9.622 ms | 15.122 ms | 0.64× |
| LU dgetrf, one-shot | 2048 | 41.828 ms | 45.878 ms | 0.91× |
| LU dgetrf, one-shot | 4096 | 266.579 ms | 174.395 ms | 1.53× |
| LU dgetrf (delegation) | 4096 | 163.36 ms | 162.99 ms | 1.00× |
perf/cuda-lapack.md · measured 2026-10-01 @ 47d8c891; delegation row: 2026-09-26 record
FFT
Host-CPU comparison (the fft harness has no GPU arm): single forward complex/real FFTs (f32/f64) vs rustfft (complex) and realfft (real). Audio band 512–4096 points, large band 1–4M points; cells are gap ranges over the sizes in each band (gap = Sonium ÷ rustfft). Full size sweep in perf/cuda-fft.md.
| Transform | Audio 512–4096 | Large 1–4M |
|---|---|---|
| complex f64 | — | — |
| complex f32 | — | — |
| real f64 | — | — |
| real f32 | — | — |
perf/cuda-fft.md (Seeded 2026-10-15 (not yet measured; regenerate with just perf-cell cuda fft))
Sparse matrix
| Workload | Size | Sonium | Vendor | Gap |
|---|---|---|---|---|
| SpMV f64 (prebaked) | 512k rows | 0.101 ms · 740 GB/s | cuSPARSE / roofline | 1.007× · near-roof |
| SpMM (prebaked) | 512k rows, 16 rhs | 1.255 ms | cuSPARSE best-alg 1.254 ms | 1.00× |
perf/cuda-sparse-matrix.md (Seeded 2026-10-01 from root PERF.md x86/GPU record (RTX PRO 6000, 2026-09-26 → 27))
Dense solvers
GPU LU via delegation at 1.00× (see LAPACK). One-shot entries carry documented non-live costs (validating 266× = full device-to-host validation; unchecked 9× = per-call prebake) — solver loops use the persistent prebaked path at parity.
perf/cuda-dense-solvers.md (seed 2026-10-01 from 2026-09-26 record)
Sparse solvers + preconditioners
Block GMRES workstation, N=512 diagonal f32, 8 rhs (2026-10-01): CPU 2.980 ms vs CUDA 2.924 ms — a tie on a tiny overhead-dominated smoke system; a production-size comparison is still open. CUDA GMRES-IR (mixed-precision refinement) converges with outer/inner residuals digit-identical to the CPU baseline, but clean-window timing is still queued (tenant contention dominates current numbers).
perf/cuda-sparse-solvers.md · measured 2026-10-01 @ 47d8c891
OpenCourant (Radioss) — head-to-head
Measured 2026-10-18 on AMD Threadripper PRO 3995WX + NVIDIA RTX PRO 6000 Blackwell. Regenerated by
website/scripts/generate_perf_data.py (also run by
just website-demos) from perf/oc/*.json
(sonium.oc-bench/v1 bundles, correctness-gated) and the
curated cavity dataset in oc-benchmarks.json; full report
in perf/oc-explicit.md (just perf-oc).
Explicit dynamics — serial vs serial
Same checked-in deck pair, material cards, and stop time on both sides; metric is ns per DOF per cycle (own adaptive dt per side, so cycle counts differ). Sonium is faster on all six decks.
| Deck | DOF | Sonium ns/dof/cycle | OpenCourant ns/dof/cycle | Speedup | Sonium wall | OpenCourant wall |
|---|---|---|---|---|---|---|
| beam_3d_cantilever | 297 | 38 | 246.1 | 6.47× | 2.949 s | 20.068 s |
| beam_torsion | 3675 | 65.3 | 116.6 | 1.79× | 198.316 s | 372.199 s |
| beam_warping | 8091 | 56.8 | 103.8 | 1.83× | 300.040 s | 576.703 s |
| bending_3pt | 567 | 39.2 | 155.8 | 3.98× | 5.797 s | 24.245 s |
| cantilever | 297 | 37.8 | 246.3 | 6.52× | 2.929 s | 20.081 s |
| foam33_cube | 24 | 59.7 | 3751.4 | 62.85× | 0.044 s | 0.524 s |
| foam76_compression | 24 | 112.1 | 4118.5 | 36.73× | 0.083 s | 0.562 s |
| foam76_tension | 24 | 89.5 | 4187.8 | 46.78× | 0.066 s | 0.570 s |
| hertz_sphere | 1455 | 60.2 | 127.9 | 2.13× | 9.200 s | 25.590 s |
| necking_bar | 297 | 146.5 | 271.6 | 1.85× | 56.823 s | 110.743 s |
| plasticity_thick_cylinder | 1872 | 117.4 | 123.1 | 1.05× | 1.034 s | 1.196 s |
| rail_crush | 297 | 156.3 | 268.6 | 1.72× | 0.303 s | 0.550 s |
| shell_clamped_plate | 771 | 149.7 | 154.1 | 1.03× | 104.273 s | 27.832 s |
| shell_oht_elastic | 12192 | 173.2 | 80.8 | 0.47× | 304.814 s | 31.818 s |
| shell_scordelis_lo | 3267 | 312.1 | 112.7 | 0.36× | 387.436 s | 10.604 s |
| shell_twisted_beam | 693 | 135.2 | 176 | 1.3× | 27.904 s | 8.873 s |
| taylor_bar | 675 | 215.9 | 2113.1 | 9.79× | 0.003 s | 0.034 s |
| taylor_plastic | 2340 | 299.9 | 434.3 | 1.45× | 0.086 s | 0.054 s |
Threaded scaling — 16 threads
Same 16 decks at 16 threads (t16 both sides): engine SMP16 runs 0.4–3.3× its own serial, so sonium wins 15 of 16 per-cycle (1.4–170.2×). Losses: beam_warping. Engine MPI best shown for context.
| Deck | Sonium t16 | Engine SMP16 | Engine MPI best | Speedup |
|---|---|---|---|---|
| beam_3d_cantilever | 38 | 788.3 | 262.9 (r4) | 20.77× |
| beam_torsion | 65.4 | 90.3 | 46.5 (r4) | 1.38× |
| beam_warping | 57.1 | 41.3 | 32 (r4) | 0.72× |
| bending_3pt | 39.4 | 456.3 | 146.3 (r4) | 11.58× |
| cantilever | 37.8 | 777.8 | 262.6 (r4) | 20.57× |
| foam33_cube | 59.7 | 10167.8 | 8345.8 (r2) | 170.2× |
| foam76_compression | 112.1 | 10624.3 | 8873.8 (r2) | 94.74× |
| foam76_tension | 89.9 | 10595.7 | 8921.2 (r2) | 117.9× |
| hertz_sphere | 59.6 | 216.3 | 82.8 (r4) | 3.63× |
| necking_bar | 152.2 | 788.3 | 255 (r4) | 5.18× |
| plasticity_thick_cylinder | 116.3 | 188.8 | 139.9 (r4) | 1.62× |
| rail_crush | 149 | 893.7 | 576.1 (r2) | 6× |
| shell_clamped_plate | 149.7 | 377.9 | 122.7 (r4) | 2.52× |
| shell_twisted_beam | 133 | 437.5 | 140.6 (r4) | 3.29× |
| taylor_bar | 217.3 | 5257.6 | 38557.9 (r2) | 24.19× |
| taylor_plastic | 298.5 | 802.3 | 5040.6 (r2) | 2.69× |
perf/oc/*.json correctness-gated bundles (2026-10-12); full matrix in perf/oc-explicit.md
Wall time to matched accuracy — lid-driven cavity
Wall time to matched accuracy: lid-driven cavity at Re=100 against Ghia reference profiles (max error gate 0.03). Sonium runs its incompressible Navier-Stokes solver; OpenCourant (Radioss) runs a low-Mach compressible ALE surrogate, its closest native option.
| Threads | Sonium | OpenCourant | Speedup | Sonium error | OpenCourant error |
|---|---|---|---|---|---|
| 1 | 15.6 s | 226.3 s | 14.5× | 0.0162 | 0.0264 |
| 8 | 11 s | 60.8 s | 5.5× | 0.0162 | 0.0264 |
| 16 / 32 | 10.8 s | 57.2 s | 5.3× | 0.0162 | 0.0264 |
GPU — Sonium CPU vs CUDA
| Case | CPU | GPU | Speedup |
|---|---|---|---|
| Lid cavity n=64 | 15.6 s | 11.6 s | 1.34× |
| Lid cavity n=128 | 354 s | 38.1 s | 9.3× |
| Taylor-Green n=128 | 23.1 s | 11.3 s | 2× |
Sonium is faster at every thread count and more accurate at the gate (0.0162 vs 0.0264 max error). Both codes saturate with threads: sonium 1.44x self-speedup at 16 threads, the engine 3.95x at 32.
Every GPU row is backend-audited per solve: a silent CPU fallback marks the row failed instead of relabeling it.
Methodology
Times are medians of repeated runs after warm-up; x86 numbers use interleaved same-process A/B.
Every backend must pass a relative residual gate (1e-10 direct, ~1e-6 iterative) before timing.
Vendor threads are tuned, never oversubscribed; Sonium x86 runs at 16 threads (its 128-thread default oversubscribes).
Box noise is ±10–15% multi-threaded; single-thread ratios are the stable comparison.
Ratios above 1.0 mean Sonium is slower than the reference; below 1.0 means faster.
Reproduce: just perf-x86 · just perf-cuda ·
just bench-lapack · just bench-petsc-run ·
per-cell reports in perf/, full report in
PERF.md (repo root).