Performance¶
Low-overhead Python calls for real Fortran workloads.
On the benchmark system, the normal PRIK interface delivered a 1.08× geometric-mean speedup over NumPy's f2py. Across 13 workloads, PRIK was faster in 10 and f2py in 2; 1 workload showed no statistically significant difference.
The chart shows f2py time ÷ PRIK time. Values to the right of 1.0× favor
PRIK; values to the left favor f2py. Results close to 1.0× are practical
parity and may move slightly between machines or runs.
Detailed Results¶
Lower times are better. Every row measures the same Fortran operation through the normal generated interface of each tool.
| Workload | f2py | PRIK | Relative result |
|---|---|---|---|
| Empty function call | 34.6 ns | 29.9 ns | PRIK 1.16× faster |
| Add two scalars | 340 ns | 359 ns | f2py 1.06× faster |
| Increment vector, 1 element | 103 ns | 80.5 ns | PRIK 1.27× faster |
| Increment vector, 16 elements | 106 ns | 82.7 ns | PRIK 1.28× faster |
| Increment vector, 1,024 elements | 262 ns | 210 ns | PRIK 1.25× faster |
| Increment vector, 1,000,000 elements | 186 µs | 183 µs | PRIK 1.02× faster |
| Sum 4×4 F-order matrix | 127 ns | 111 ns | PRIK 1.15× faster |
| Sum 32×32 F-order matrix | 718 ns | 701 ns | PRIK 1.02× faster |
| Sum 256×256 F-order matrix | 38.9 µs | 39.0 µs | No significant difference |
| Sum 1,024×1,024 F-order matrix | 620 µs | 621 µs | f2py 1.002× faster |
| Update 4×4 F-order matrix | 247 ns | 241 ns | PRIK 1.03× faster |
| Update 256×256 F-order matrix | 13.1 µs | 12.8 µs | PRIK 1.02× faster |
| Update 1,024×1,024 F-order matrix | 198 µs | 194 µs | PRIK 1.02× faster |
| Geometric mean | reference | — | PRIK 1.08× faster |
The smallest workloads expose wrapper overhead most clearly. As more time is spent inside Fortran, both tools approach the cost of the native operation and small differences matter less.
Clean Build Time¶
Build latency is measured separately from runtime-call overhead. Each timing starts with an empty output directory and ends when the normal tool command has generated its wrapper, compiled all native and generated sources, and linked an extension. Importability and the expected Python exports are checked immediately afterward, outside the timed interval.
The small-module workload uses the same one-source, five-procedure module as the
runtime suite. The full-library workload gives both tools the same 155-source
reference BLAS implementation and requires all 155 routines to be exposed.
Each workload is built once as a development build with -O0 and once as an
optimized build with -O3 -march=native -mtune=native.
Each value is the mean of 6 clean builds after 1 untimed warm-up.
| Clean build workload | f2py | PRIK | Relative result |
|---|---|---|---|
Development (-O0) · small module (1 source, 5 procedures) |
1.41 sec | 494 ms | PRIK 2.86× faster |
Development (-O0) · full reference BLAS (155 sources) |
6.85 sec | 5.48 sec | PRIK 1.25× faster |
Optimized (-O3 -march=native -mtune=native) · small module (1 source, 5 procedures) |
1.63 sec | 590 ms | PRIK 2.76× faster |
Optimized (-O3 -march=native -mtune=native) · full reference BLAS (155 sources) |
10.8 sec | 13.6 sec | f2py 1.26× faster |
Fair, Like-for-Like Setup¶
The suite wraps one set of Fortran kernels with the default PRIK and f2py interfaces. It checks both extensions for the same results before measuring them. No benchmark-only wrapper mode is used.
- Runtime native and generated sources use
-O3 -march=native -mtune=native. - Clean builds use development (
-O0) and optimized (-O3 -march=native -mtune=native) profiles. - Both interfaces keep the GIL held.
- OpenMP, OpenBLAS, and MKL are limited to one thread.
pyperf --rigorouspins each benchmark to logical CPU0.- PRIK build timings use up to 4 concurrent compiler processes; f2py uses its normal Meson/Ninja scheduler.
- Build timings alternate tool order, use clean output directories, and exclude post-build import checks.
- CPU: Arm Neoverse N2.
- Operating system: Ubuntu 24.04.4 LTS.
- Kernel/platform:
Linux-6.17.0-1020-azure-aarch64-with-glibc2.39. - Python: 3.12.13.
- NumPy/f2py: 2.5.1.
- Fortran compiler: GNU Fortran 13.3.0.
- pyperf: 2.10.0.
- PRIK revision:
1787267cf673.
These results were recorded on August 3, 2026. Performance depends on the CPU, compiler, operating system, and background activity, so comparisons should use results produced together on the same machine.
Reproduce the Results¶
The complete benchmark suite is included in the repository. From the repository root, reproduce the build, correctness checks, measurements, and comparison with one command:
bash benchmarks/run.sh
The command writes the runtime and clean-build pyperf result pairs under
benchmarks/results/ and prints both comparison tables.