Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

README.md

Performance

Measured numbers only. Each benchmark gets one file: tables + one-line notes. Method notes live at file bottom; narrative archives in docs/notes/.

Machine-tag rule (S26, Sapir — standing): every results CSV carries a machine-spec comment header (# utc / cpu / threads / core_quota / ram_gb / clang — stamped by benches/matmul/runner.py); every comparison table is one machine; cross-machine numbers only as explicitly labeled cross-session rows.

Benchmark Compares Latest File
Matmul GEMM flow-cuda · flow-llvm · interp vs naive CUDA · cuBLAS · numpy · Rust · C++ · Chapel 2026-07-22 (S20) matmul.md
Arena allocation malloc/free API-call counts, structural 2026-07-21 (v1.0) arena.md

Headline (current truth)

What Number Note
flow-cuda matmul kernel time (N=256) 0.205 ms · 163 GFLOP/s FLOW_PERF-instrumented (S20); ~10–17× off naive CUDA — the next target (Index-guard elimination)
flow-cuda matmul process wall (N=64) 313 ms startup-bound; still beats naive-C/cuBLAS binaries at equal terms
speedup vs own loop form 40× (N=64) · 321× (N=128) wall time
flow-llvm vs C++ (znver2, N=64) 9.17 vs 0.254 ms (loop) · 29.17 vs 0.254 (capture) was 316 / 2,076 ms pre-W1/W2 — Index-guard vectorization is the residual
chapel vs flow-cuda kernel chapel f64 0.897 ms @ N=256 direct-competitor row; chapel wins ≤256, cliff at 512+
arena allocation 8 → 1 cudaMalloc/free (capture matmul) smart arenas v1.0; structural, CI-asserted
correctness interp = flow-cuda = naive CUDA = numpy at every N outputs byte-checked
peak measured anywhere cuBLAS 58.8 TF/s (N=4096) the tiling ceiling, untouched by language
  • conv2d-per-core-gap.mdRESOLVED (S33): it was a measurement boundary, not a kernel defect. Flow's timed window included the output array's first-touch page-zeroing; the C++ baseline pre-pays that outside its window (std::vector value-initialises). Exact differenced counters put Flow's kernel at 18% fewer cycles and 22% less real time than C++'s, IPC 2.25 vs 1.78. Fixed by reside in flow_rt_alloc; conv2d is now 1.21x AHEAD of naive C++ per core on both NEON and AVX2. The eight eliminated in-kernel causes were all correctly refuted — the kernel was never the problem. The recorded "IPC 3.11 vs 1.57" was process-level, contaminated by Flow's generation legs.
  • s39-guards-gate-the-flow.mdS39: no performance change, and the timing runs are not what proves it. The guard-gating change (an arm that is not taken does not run) emits byte-identical LLVM IR for 103 of 104 bench/matmul/example × face combinations — the one change is examples/calc.mapal, the only file in the tree with a trapping guard arm — and those link to byte-identical binaries. Identical machine code cannot run at a different speed, so the artifact A/B is the result and the stopwatch is not. The timings are kept as a noise-floor measurement: 51 alternating runs × 6 shapes on the M4 Pro spread −5.89%…+1.18% between the same bytes, with within-side max/min reaching 4.93×. That is S38's measurement rule 6 in its strongest form — under ~6% on an unpinned Mac at sub-millisecond sizes is nothing; claiming less needs the pinned i9. Also records why there is no regression to explain: gating is legality-then-cost, and the "leave two scalar arms alone" clause exists because an earlier version branched inside sepia's per-element map body, which the A/B caught.
  • matmul/s33.mdS33: both machines, full suite. The boundary fix above, plus the cross-machine AMX test: on the i9 (no matrix coprocessor, numpy → OpenBLAS 0.3.30 on the same AVX2 units) Flow's generated GEMM reaches PARITY with hand-tuned OpenBLAS — 1t a flat 1.20x behind at 1024/2048/4096 (146 vs 174 GFLOP/s, both size-invariant), threaded within ±10% (ahead at 2048, behind at 512 and 4096) — while the M4's AMX-backed numpy is 3.3x ahead. The M4 matmul gap is hardware, now measured rather than argued. Confound checked: OpenBLAS does use all 32 threads. Flow scales 9.2–9.8x vs OpenBLAS's 7.1–8.1x, but the "better scheduler" reading was tested and refuted: on uniform cores OpenBLAS wins (5% on 8 E-cores, 41% on 8 P-cores) and Flow wins only on a mixed set (1.65x on 4P+4E). It is heterogeneity tolerance, not a better scheduler — see s33.md §4. Also P0: a help-first race in flow_par_wait invalidates every par minimum (3–4% of threaded runs self-time far too low — one live case read 0.0001 ms; min is the wrong statistic, median is stable) — pre-existing, unrelated to the fix.