Native-core P0 baseline¶
Historical pre-native capture only. These measurements do not describe the 0.6.1 release and must not be used as current performance headlines.
This document records the pre-native correctness and performance baseline. It is a comparison point for the Rust CPU and CUDA engines, not a general throughput promise.
Captured environment¶
The baseline was captured on 2026-07-28 from commit
fffffabef278ac1d9162141151f98da960f194c4 plus the P0 measurement scripts.
| Component | Value |
|---|---|
| OS | Windows 10.0.26200 x86-64 |
| CPU | AMD Ryzen 9 9900X 12-Core Processor |
| GPU | NVIDIA GeForce RTX 5070 Ti, 16,303 MiB |
| GPU compute capability | 12.0 |
| NVIDIA driver | 596.49 |
| CUDA toolkit/runtime | 12.9 |
| Python | 3.11.0 |
| NumPy | 2.4.6 |
| CuPy | 14.1.1 |
| Nsight Systems | 2025.3.2 |
| Nsight Compute | 2025.2.0; CLI capture unavailable, noted below |
Raw, schema-versioned summaries are committed as:
benchmarks/baselines/p0-windows-rtx5070ti-shape-sweep.jsonbenchmarks/baselines/p0-windows-rtx5070ti-nsys-summary.json
Binary .nsys-rep, .sqlite, and future .ncu-rep reports remain under the
ignored artifacts/ directory.
Shape sweep¶
The complete sweep measures both penalties, both supported dtypes, and NumPy, host-fed CUDA, and device-resident CUDA. Each number below is the median of three warm runs. Data generation and device preload are outside the device-resident timing.
Representative unpenalized float32 results:
| Shape | NumPy CPU | CUDA host input | CUDA device input | Device/CPU |
|---|---|---|---|---|
| latency: 4,096 x 16 | 3.71 M samples/s | 0.44 M | 0.46 M | 0.12x |
| reference: 100,000 x 90 | 1.56 M samples/s | 4.10 M | 4.57 M | 2.93x |
| wide: 16,384 x 256 | 21.8 K samples/s | 397.7 K | 406.8 K | 18.64x |
| streaming: 1,000,000 x 32 | 4.98 M samples/s | 13.71 M | 15.99 M | 3.21x |
The result establishes three dispatch requirements:
- Small problems belong on CPU because CUDA launch and synchronization costs dominate.
- The unpenalized weighted-Gram path benefits strongly from CUDA as feature count grows.
- L1 does not consistently benefit from CUDA yet. For example, reference
float32L1 measured 2.31 M samples/s on CPU and 1.01 M samples/s with device-resident CUDA. The native CUDA loop must reduce launch and scalar synchronization overhead before becoming the default L1 engine.
Reproduce the complete sweep:
python scripts/benchmarks/benchmark_shape_sweep.py `
--profile standard --backend both --penalty both --dtype both `
--warmup 1 --repeats 3 `
--output artifacts/p0-shape-sweep.json
Use --profile smoke before longer runs. A named standard case can be selected
with --case latency, --case reference, --case wide, or
--case streaming. Each named case has a stable derived seed whether it is run
alone or as part of the full profile.
Nsight Systems baseline¶
The timeline workload used two device-resident batches with 8,192 total rows,
32 features, unpenalized float32, three measured repetitions, and eight
solver iterations per repetition.
Within the three profile/repeat-* NVTX ranges, Nsight recorded:
| Metric | Count or duration | Per solver iteration |
|---|---|---|
| CUDA kernels | 2,067 | 86.1 |
| Device-to-host copies | 168 copies / 492 bytes | 7.0 copies |
| Stream wait synchronizations | 174 | 7.25 |
| CUDA kernel execution | 3.28 ms | 0.137 ms |
| Profile range window | 49.63 ms | 2.07 ms |
cudaMemcpyAsync host API time |
14.29 ms | 0.60 ms |
Only 492 bytes moved from device to host, but those scalar copies created 168 separate transfers. This confirms that transfer volume is not the problem; frequency and synchronization are. Kernel execution occupied a small fraction of the profiled wall-time window, while scalar copies, launch dispatch, and stream waits dominated host-side time.
The most expensive individual kernel family in this small workload was the cuSOLVER LU factorization path. The trace contains one factorization per solver iteration. P1/P2 should therefore:
- move the complete solver loop behind one native call;
- keep convergence and line-search scalars on device as long as possible;
- cache handles and workspaces;
- use a Cholesky fast path for positive-definite Hessians;
- retain a tested QR/least-squares fallback;
- continue using vendor GEMV/GEMM instead of custom matrix multiplication.
Capture and summarize a new Systems report:
.\scripts\profiling\run_nsight_systems.ps1 `
-Python python `
-Samples 100000 -Features 90 -BatchSize 32768
The wrapper finds an installed Windows Nsight Systems CLI even when nsys is
not on PATH. It emits the binary report, SQLite export, workload metadata,
and a range-filtered JSON summary under artifacts/nsight/.
The summary can also be regenerated independently:
python scripts/profiling/summarize_nsys_sqlite.py `
artifacts/nsight/native-core-p0-systems.sqlite `
--metadata artifacts/nsight/native-core-p0-systems.json `
--output artifacts/nsight/native-core-p0-summary.json
Nsight Compute status¶
The P0 repository includes run_nsight_compute.ps1 with a bounded launch count
and the same NVTX-instrumented workload. On the capture machine, Nsight Compute
2025.2.0 printed its version successfully but its CLI exited with Windows code
-1073740791 even for --list-sets; no trustworthy counter report was
produced. The failure occurs before the Python workload starts.
This is recorded as a tooling gap rather than fabricated occupancy or roofline data. After repairing or upgrading the local Nsight Compute installation, run:
.\scripts\profiling\run_nsight_compute.ps1 `
-Python python `
-Samples 100000 -Features 90 -BatchSize 32768 `
-LaunchCount 50
Nsight Compute metrics are not a gate for starting the Rust CPU engine. CUDA-specific kernel tuning beyond the Systems findings remains gated on a valid Compute report.
Correctness baseline¶
tests/golden/native_core_v1.json freezes four differential cases:
- weighted unpenalized two-batch
float64; - L1 two-batch
float64; - outlier-heavy, no-intercept
float32; - rank-deficient, zero-ridge least-squares fallback.
Regenerate or verify it with:
Golden changes require a documented algorithm correction or an RFC amendment. Iteration counts are diagnostic; final state, portable metadata, diagnostics, and predictions are compared with case-specific tolerances.