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×).

Shapef32f64Reading
sq 64/256/1024 NN1.00–1.03×0.97–1.00×parity-or-better
thin 2048x128x20480.89×0.64×we win
gemv, all shapes0.03–0.79×0.09–0.72×we win big
nrm2, all n0.36–0.50×0.29–0.50×we win
axpy/dot/scal real, large n1.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.

WorkloadSizeSoniumAccelerateGap
Cholesky dpotrf204841.410 ms15.436 ms2.68×
Cholesky dpotrf4096298.598 ms141.331 ms2.11×
LU dgetrf204870.679 ms51.922 ms1.36×
LU dgetrf4096764.924 ms320.200 ms2.39×
LU sgetrf204828.757 ms44.173 ms0.65×
QR dgeqrf2048665.609 ms357.880 ms1.86×
QR dgeqrf40966.344 s2.446 s2.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).

nSolveIterationsResidualEff. SpMV BW
9610.41 ms128.5e-072.86 GB/s
10,0004.62 ms145.2e-073.13 GB/s
99,85672.98 ms186.7e-072.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×.

NSoniumAccelerateGapResidual
640.113 ms0.052 ms2.17×8.71e-16
1280.423 ms0.152 ms2.78×1.22e-15
2561.788 ms0.863 ms2.07×1.66e-15
5123.791 ms2.168 ms1.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.

nSolveIterationsResidual
9610.41 ms128.5e-07
10,0004.62 ms145.2e-07
99,85672.98 ms186.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.

Shapef32f64Reading
sq 64/256/1024 NN0.96–1.10×0.93–1.01×parity-or-better
thin 2048x128x20480.32×0.69×we win
gemv, all shapes0.03–0.52×0.06–0.66×we win big
nrm2, all n0.30–0.52×0.29–0.58×we win
axpy/dot/scal real, large n3.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.

WorkloadSizeSoniumAccelerateGap
Cholesky dpotrf204823.632 ms19.055 ms1.24×
Cholesky dpotrf4096141.269 ms119.643 ms1.18×
LU dgetrf2048234.660 ms50.370 ms4.66×
LU dgetrf4096781.804 ms247.696 ms3.16×
LU sgetrf204823.110 ms40.650 ms0.57×
QR dgeqrf2048215.277 ms148.843 ms1.45×
QR dgeqrf40961.626 s1.043 s1.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.

TransformAudio 512–4096Large 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).

nSolveIterationsResidualEff. SpMV BW
9610.41 ms128.5e-072.88 GB/s
10,0003.61 ms145.2e-074.01 GB/s
99,85672.86 ms186.6e-072.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×.

NSoniumAccelerateGapResidual
640.027 ms0.014 ms1.91×8.71e-16
1280.262 ms0.057 ms4.56×1.22e-15
2561.003 ms0.307 ms3.27×1.77e-15
5122.989 ms1.612 ms1.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×.

GridNSimplicial / SLUSupernodal / SLU
8×8641.34×2.49×
12×121441.49×2.74×
16×162561.64×3.86×
20×204001.78×3.07×
28×287841.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.

nSolveIterationsResidual
9610.41 ms128.5e-07
10,0003.61 ms145.2e-07
99,85672.86 ms186.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.

Shapef32f64Reading
sq 256/512/1024 NN0.8–1.05×0.5–1.0×parity-or-better
sq 2048 NN1.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.

WorkloadSizeSoniumVendorGap
Cholesky dpotrf204819.86 ms14.68 ms1.35×
Cholesky dpotrf409693.53 ms69.67 ms1.34×
Cholesky spotrf20488.75 ms7.18 ms1.22×
LU dgetrf204840.92 ms29.02 ms1.41×
LU dgetrf4096272.04 ms132.66 ms2.05×
LU sgetrf204825.15 ms16.17 ms1.55×
QR dgeqrf+dorgqr2048323.17 ms249.40 ms1.30×
QR dgeqrf+dorgqr40961578.56 ms1433.44 ms1.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.

TransformAudio 512–4096Large 1–4M
complex f641.09–2.03×1.40–1.60×
complex f320.83–1.33×1.52–1.84×
real f640.95–1.24×1.45–1.88×
real f320.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.

nSolveIterationsResidualEff. SpMV BW
9610.57 ms128.5e-072.05 GB/s
10,0006.82 ms145.2e-072.12 GB/s
99,85695.15 ms186.7e-071.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.

WorkloadSoniumOpenBLASGapGate
LU dgetrf-1024, in-place8.67–9.06 ms7.42 ms1.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.

CellnSimplicial / SLUSupernodal / SLU
32² conv-diff10241.68×2.15×
40² conv-diff16001.82×2.12×
128² conv-diff163843.7×1.8×
128² Laplacian163843.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 + precondMatrixnSoniumPETScGap
FGMRES + AMGPoisson 2-D99,856105.11 ms99.78 ms1.05×
CG + AMGPoisson 2-D99,85692.99 ms72.15 ms1.29×
CG + AMGLaplacian 3-D97,336111.13 ms75.44 ms1.47×
CG + AMGaniso. diffusion99,85656.70 ms35.74 ms1.59×
GMRES + ILUsaddle point99,372132.17 ms88.54 ms1.49×
CG + JacobiLaplacian 3-D97,336321.11 ms116.26 ms2.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.

WorkloadGap vs cuBLASCorrectness
dgemm1.000×bitwise
sgemm1.001×bitwise
dgemv0.994×bitwise
sgemv1.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.

WorkloadSizeSoniumcuSOLVERGap
LU dgetrf, one-shot5122.837 ms5.622 ms0.50×
LU dgetrf, one-shot10249.622 ms15.122 ms0.64×
LU dgetrf, one-shot204841.828 ms45.878 ms0.91×
LU dgetrf, one-shot4096266.579 ms174.395 ms1.53×
LU dgetrf (delegation)4096163.36 ms162.99 ms1.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.

TransformAudio 512–4096Large 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

WorkloadSizeSoniumVendorGap
SpMV f64 (prebaked)512k rows0.101 ms · 740 GB/scuSPARSE / roofline1.007× · near-roof
SpMM (prebaked)512k rows, 16 rhs1.255 mscuSPARSE best-alg 1.254 ms1.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.

DeckDOFSonium ns/dof/cycleOpenCourant ns/dof/cycleSpeedupSonium wallOpenCourant wall
beam_3d_cantilever297 38246.1 6.47× 2.949 s20.068 s
beam_torsion3675 65.3116.6 1.79× 198.316 s372.199 s
beam_warping8091 56.8103.8 1.83× 300.040 s576.703 s
bending_3pt567 39.2155.8 3.98× 5.797 s24.245 s
cantilever297 37.8246.3 6.52× 2.929 s20.081 s
foam33_cube24 59.73751.4 62.85× 0.044 s0.524 s
foam76_compression24 112.14118.5 36.73× 0.083 s0.562 s
foam76_tension24 89.54187.8 46.78× 0.066 s0.570 s
hertz_sphere1455 60.2127.9 2.13× 9.200 s25.590 s
necking_bar297 146.5271.6 1.85× 56.823 s110.743 s
plasticity_thick_cylinder1872 117.4123.1 1.05× 1.034 s1.196 s
rail_crush297 156.3268.6 1.72× 0.303 s0.550 s
shell_clamped_plate771 149.7154.1 1.03× 104.273 s27.832 s
shell_oht_elastic12192 173.280.8 0.47× 304.814 s31.818 s
shell_scordelis_lo3267 312.1112.7 0.36× 387.436 s10.604 s
shell_twisted_beam693 135.2176 1.3× 27.904 s8.873 s
taylor_bar675 215.92113.1 9.79× 0.003 s0.034 s
taylor_plastic2340 299.9434.3 1.45× 0.086 s0.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.

DeckSonium t16Engine SMP16Engine MPI bestSpeedup
beam_3d_cantilever38788.3 262.9 (r4) 20.77×
beam_torsion65.490.3 46.5 (r4) 1.38×
beam_warping57.141.3 32 (r4) 0.72×
bending_3pt39.4456.3 146.3 (r4) 11.58×
cantilever37.8777.8 262.6 (r4) 20.57×
foam33_cube59.710167.8 8345.8 (r2) 170.2×
foam76_compression112.110624.3 8873.8 (r2) 94.74×
foam76_tension89.910595.7 8921.2 (r2) 117.9×
hertz_sphere59.6216.3 82.8 (r4) 3.63×
necking_bar152.2788.3 255 (r4) 5.18×
plasticity_thick_cylinder116.3188.8 139.9 (r4) 1.62×
rail_crush149893.7 576.1 (r2) 6×
shell_clamped_plate149.7377.9 122.7 (r4) 2.52×
shell_twisted_beam133437.5 140.6 (r4) 3.29×
taylor_bar217.35257.6 38557.9 (r2) 24.19×
taylor_plastic298.5802.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.

ThreadsSoniumOpenCourantSpeedupSonium errorOpenCourant error
115.6 s226.3 s 14.5× 0.01620.0264
811 s60.8 s 5.5× 0.01620.0264
16 / 3210.8 s57.2 s 5.3× 0.01620.0264

GPU — Sonium CPU vs CUDA

CaseCPUGPUSpeedup
Lid cavity n=6415.6 s11.6 s 1.34×
Lid cavity n=128354 s38.1 s 9.3×
Taylor-Green n=12823.1 s11.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).