Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,13 @@ jobs:
benchmarks/results/f2py.json \
benchmarks/results/prik.json \
benchmarks/results/f2py-build.json \
benchmarks/results/prik-build.json
benchmarks/results/prik-build.json \
benchmarks/results/f2py-direct.json \
benchmarks/results/prik-direct.json \
benchmarks/results/prik-adapted.json \
benchmarks/results/f2py-direct-build.json \
benchmarks/results/prik-direct-build.json \
benchmarks/results/prik-adapted-build.json

- name: Upload Performance snapshot and raw results
uses: actions/upload-artifact@v4
Expand All @@ -100,11 +106,30 @@ jobs:
benchmarks/results/prik-f2py-first.json
benchmarks/results/f2py-build.json
benchmarks/results/prik-build.json
benchmarks/results/f2py-direct.json
benchmarks/results/prik-direct.json
benchmarks/results/prik-adapted.json
benchmarks/results/f2py-direct-forward.json
benchmarks/results/f2py-direct-reverse.json
benchmarks/results/prik-direct-forward.json
benchmarks/results/prik-direct-reverse.json
benchmarks/results/prik-adapted-forward.json
benchmarks/results/prik-adapted-reverse.json
benchmarks/results/f2py-direct-build.json
benchmarks/results/prik-direct-build.json
benchmarks/results/prik-adapted-build.json
docs/user/performance.md
docs/user/assets/performance-comparison.svg
docs/user/assets/build-time-comparison.svg
retention-days: 90

- name: Upload direct-entrypoint artifact preflight
uses: actions/upload-artifact@v4
with:
name: direct-entrypoint-preflight
path: benchmarks/build/direct-runtime
retention-days: 90

build:
name: Documentation site build · Ubuntu 24.04 · Python 3.12
needs: benchmark
Expand Down
27 changes: 26 additions & 1 deletion .github/workflows/merge-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,13 @@ jobs:
benchmarks/results/f2py.json \
benchmarks/results/prik.json \
benchmarks/results/f2py-build.json \
benchmarks/results/prik-build.json
benchmarks/results/prik-build.json \
benchmarks/results/f2py-direct.json \
benchmarks/results/prik-direct.json \
benchmarks/results/prik-adapted.json \
benchmarks/results/f2py-direct-build.json \
benchmarks/results/prik-direct-build.json \
benchmarks/results/prik-adapted-build.json
- name: Upload Performance snapshot and raw results
uses: actions/upload-artifact@v4
with:
Expand All @@ -621,11 +627,30 @@ jobs:
benchmarks/results/prik-f2py-first.json
benchmarks/results/f2py-build.json
benchmarks/results/prik-build.json
benchmarks/results/f2py-direct.json
benchmarks/results/prik-direct.json
benchmarks/results/prik-adapted.json
benchmarks/results/f2py-direct-forward.json
benchmarks/results/f2py-direct-reverse.json
benchmarks/results/prik-direct-forward.json
benchmarks/results/prik-direct-reverse.json
benchmarks/results/prik-adapted-forward.json
benchmarks/results/prik-adapted-reverse.json
benchmarks/results/f2py-direct-build.json
benchmarks/results/prik-direct-build.json
benchmarks/results/prik-adapted-build.json
docs/user/performance.md
docs/user/assets/performance-comparison.svg
docs/user/assets/build-time-comparison.svg
retention-days: 90

- name: Upload direct-entrypoint artifact preflight
uses: actions/upload-artifact@v4
with:
name: direct-entrypoint-preflight
path: benchmarks/build/direct-runtime
retention-days: 90

documentation-build:
name: Documentation site build · Ubuntu 24.04 · Python 3.12
needs: documentation-benchmark
Expand Down
33 changes: 33 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,39 @@ release tags add a leading `v` to the package version.

## Unreleased

### Added

- Added a native-entrypoint adoption roadmap for selective direct Fortran
`bind(C)` calls and the initial direct-only C wrapper backend, including
conservative starter-contract defaults for ambiguous C pointers.
- Added `@native_abi("c")` to semantic `.pyi` contracts so Fortran `bind(C)`
procedures retain their ABI and optional link label through generated and
source-free contract workflows.
- Added selective direct routing for policy-proved Fortran `bind(C)` procedures,
including direct/mixed compiled feature fixtures and support-only generated
Fortran artifacts where independent helpers remain necessary.
- Added a separate direct-entrypoint PRIK/f2py runtime and clean-build benchmark
cohort with untimed correctness, generated-source membership, and linked
direct-symbol preflight, plus an ordinary-Fortran PRIK control.

### Changed

- Made nested semantic classes use the same complete planning and backend-symbol
allocation path as top-level classes.
- Published the maintained-run direct-entrypoint runtime, adapter-control, and
clean-build results separately from the normal-interface benchmark cohort.
- Made direct-entrypoint benchmark preflight identify binding and native
objects by their inspected symbol relationships across f2py build backends.
- Reduced exact numeric-scalar call overhead by using typed NumPy scalar
payload access and result allocation while preserving strict dtype checking
and exact NumPy result types.
- Separated wrapper plans into strict binding, shared native-entrypoint, and
Fortran-adapter facets, with planner-owned generated support procedure
entrypoints for accessors, lifecycles, descriptors, and callbacks, without
changing generated wrappers.
- Build manifest schema 3 records physical generated sources and separate
adapter/support membership, including zero-generated-native builds.

## 0.3.0 — 2026-08-14

### Added
Expand Down
62 changes: 58 additions & 4 deletions benchmarks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,28 @@ This suite compares wrappers generated by prik and NumPy's f2py on the same
machine. It measures both runtime call and NumPy-array overhead and clean,
end-to-end build time.

The existing default-interface cohort remains unchanged. A separate
direct-entrypoint cohort uses `sources/direct_kernels.f90` for a no-op, scalar
function, and scalar subroutine. PRIK must call each `bind(C)` label without a
generated user-procedure adapter. f2py retains its Python C/API binding while
using `--no-wrap-functions --skip-empty-wrappers`; those flags suppress
unneeded generated Fortran procedure wrappers/files, not the Python binding.
An untimed preflight checks correctness, records the physical generated and
compiled sources, and verifies that each direct Python binding object refers to
the three user `bind(C)` labels while the native object and linked extension
define those labels. Object discovery uses those symbol relationships rather
than backend-specific filenames because Meson retains source suffixes in object
names while other f2py backends do not. The selected binding and native object
paths are recorded in the preflight report. These checks finish before either
cohort enters a timer.

Every scalar case receives the same pre-created `numpy.float64` inputs and
produces the same numerical value. The timed calls retain each tool's natural
public result: PRIK returns the contract's exact `numpy.float64`, while f2py
returns a built-in `float`. The preflight checks those classes explicitly and
the runtime metadata records the result contract; the benchmark does not hide
the difference behind an untimed or Python-level normalization shim.

The default prik wrapper and the f2py wrappers measured here keep the GIL held,
so the suite reports one like-for-like comparison of their normal generated
interfaces.
Expand Down Expand Up @@ -59,6 +81,20 @@ per-tool JSON suites, so comparison and publication commands remain unchanged.
The script retains f2py's generated sources under `build/f2py` for local
inspection.

Direct-entrypoint results are written separately as
`prik-direct.json`/`f2py-direct.json`, while the ordinary-Fortran PRIK control
is `prik-adapted.json`. Their clean-build counterparts end in `-build.json`.
Metadata identifies the `direct_c_abi` or `generated_fortran_adapter` route,
f2py wrapper mode, natural result class, compiler flags, process order,
affinity protocol, and inspected source membership. These files are published
as separate tables and are never merged into the default cohort or its
geometric mean.

The three-route runtime control uses a forward/reverse sequence:
PRIK-direct, f2py-direct, PRIK-adapted, followed by PRIK-adapted,
f2py-direct, PRIK-direct. Clean-build rounds use the same reversal. This
balances every pair instead of always measuring the adapted control last.

To compare existing results without rebuilding:

```bash
Expand All @@ -77,15 +113,24 @@ python3 -m pyperf compare_to \
--table
```

Compare the direct-entrypoint cohort with:

```bash
python3 -m pyperf compare_to results/f2py-direct.json results/prik-direct.json --table
python3 -m pyperf compare_to results/prik-adapted.json results/prik-direct.json --table
python3 -m pyperf compare_to results/f2py-direct-build.json results/prik-direct-build.json --table
python3 -m pyperf compare_to results/prik-adapted-build.json results/prik-direct-build.json --table
```

Results are machine-specific. Compare files produced in the same run; CPU,
compiler, Python, and NumPy differences can otherwise dominate small timings.
The generated build directories, extensions, and result files are local
artifacts rather than repository sources.

## Publish a Documentation Snapshot

After a completed run, refresh the generated sections of the public Performance
page and its chart with:
After a complete paired run on the maintained benchmark runner, refresh the
generated sections of the public Performance page and its chart with:

```bash
python3 tools/generate_performance_docs.py
Expand All @@ -94,9 +139,14 @@ python3 tools/generate_performance_docs.py
Run this command from the repository root. It reads the runtime and build-time
`pyperf` pairs, checks that each pair contains the same benchmarks and compatible
platform metadata, records the host operating-system distribution and compiler,
and updates only the marked result sections in `docs/user/performance.md` plus
the runtime and clean-build comparison SVGs in `docs/user/assets/`.
and updates only the marked normal, direct, adapter-control, and build result
sections in `docs/user/performance.md` plus the normal runtime and clean-build
comparison SVGs in `docs/user/assets/`.
Explanatory prose and the reproduction instructions remain hand-maintained.
Do not publish a local sample or revise the default cohort's geometric-mean
population. The generator keeps the direct-entrypoint and adapter-control
results in their own published sections and requires compatible maintained-run
metadata across every cohort.

The Documentation workflow performs the same generation after successful
correctness checks and rigorous measurements on pushes to `main`. The benchmark
Expand All @@ -106,6 +156,10 @@ ARM64 with the expected Neoverse N2/Cobalt 100 CPU part before measuring. The
documentation build and deployment remain separate x86-64 jobs. The workflow
keeps the raw `pyperf` files as an artifact and overlays the generated snapshot
only in the website build; it does not create a result commit.
It also uploads the complete untimed direct-entrypoint preflight directory as a
separate artifact so the pinned generated C sources, binding/native objects,
linked extensions, and symbol report remain inspectable alongside the
published timing tables.

The publication environment pins Python 3.12, NumPy/f2py 2.5.1, pyperf 2.10.0,
Meson 1.11.2, Ninja 1.13.0, GNU Fortran 13, and the ARM64 runner label. Update
Expand Down
Loading
Loading