Benchmark snapshot — 2026-06-29 · 2d16f477
Official NumSharp-vs-NumPy 3-size comparison + the five matrix subsystems, persisted for provenance. Auto-generated by benchmark/scripts/snapshot_history.py.
Provenance
| Run timestamp | 20260629-083502 |
| Git HEAD | 2d16f477 — test(drawing): edge-case and data-loss/corruption coverage … |
| Working tree | clean (HEAD exactly) |
| Date | 2026-06-29 |
Environment
| CPU | 13th Gen Intel Core i9-13900K |
| OS | Windows 11 (10.0.26200) |
| .NET SDK | 10.0.101 (net10.0, Release) |
| Python | 3.12.12 |
| NumPy | 2.4.2 |
Convention
Ratio = NumPy_ms ÷ NumSharp_ms (NPY/NS) → >1.0× = NumSharp faster (higher is better).
Methodology
- C#: BenchmarkDotNet,
OfficialBenchmarkConfig— InProcessEmit toolchain, 50 measured iterations / 5 warmup, iteration time capped at 25 ms. MemoryDiagnoser on. - NumPy: 50 timed iterations / 10 warmup per op (warm long-lived interpreter).
- Sizes: 1,000 / 100,000 / 10,000,000 elements. Same seeds both sides.
- Join keyed on (op, dtype, N).
- Subsystems appended to
benchmark-report.md: NDIter, Layout, Operand, Cast, Fusion.
Headline — op-matrix geomean by size (NPY/NS, >1 = NumSharp faster)
| Size | geomean | %NumPy🕐 | ✅ / 🟡 / 🟠 / 🔴 |
|---|---|---|---|
| 1,000 | 1.13x | 89% | 116 / 58 / 35 / 11 |
| 100,000 | 0.98x | 102% | 295 / 135 / 124 / 35 |
| 10,000,000 | 1.39x | 72% | 427 / 136 / 24 / 4 |
Overall op-matrix: 1851 ops | ✅ 838 | 🟡 329 | 🟠 183 | 🔴 50 | ▫ 388 | ⚪ 63.
NDIter: HEADLINE — operation matrix: 1.20× geomean · 83%🕐 of NumPy's time · 77 win / 53 lose over 130 cells
Cast: 118 / 1568 comparable cells lag (<1.0); 1450 win (≥1.0).
Files
| file | what |
|---|---|
benchmark-report.md |
op-matrix (per-(op,dtype,N) ratio) + appended NDIter/Layout/Operand/Cast/Fusion |
benchmark-report.json / .csv |
unified machine-readable / spreadsheet form |
numpy-results.json |
raw NumPy timings (merge input) |
nditer_results.* + cards/ |
iterator benchmark sheet + README cards |
layout_/operand_/cast_/fusion_results.* |
the four matrix-subsystem sheets |
Raw BenchmarkDotNet per-class JSON (~tens of MB) is not persisted here (regenerable). Reproduce with python benchmark/run_benchmark.py.