Skip to content
Draft
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
15 changes: 10 additions & 5 deletions .github/workflows/bench.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,16 @@ jobs:
run: |
just bench-bmf "$BENCHER_LABEL" > bmf.json

- name: Upload the raw measurement
if: always()
uses: actions/upload-artifact@v7
with:
name: bench-${{ inputs.label }}
path: |
bmf.json
benches/results/*.json
if-no-files-found: warn

- uses: bencherdev/bencher@v0.6.12

# The project slug and API key go through the environment rather than the
Expand Down Expand Up @@ -105,11 +115,6 @@ jobs:
--threshold-max-sample-size 64 \
--threshold-lower-boundary _ \
--threshold-upper-boundary 0.10 \
--threshold-measure resting-memory \
--threshold-test percentage \
--threshold-max-sample-size 64 \
--threshold-lower-boundary _ \
--threshold-upper-boundary 0.10 \
--threshold-measure terms \
--threshold-test percentage \
--threshold-max-sample-size 1 \
Expand Down
24 changes: 17 additions & 7 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,19 @@ The root `pyproject.toml` declares a `[tool.uv.workspace]`, so one `uv.lock` cov
- `monoprop` (repository root, `src/monoprop/`) β€” the library, built by scikit-build-core.
- `packages/monoprop-bench-tools/` (`monoprop_bench_tools`) β€” the reusable half of the benchmark
harness, published to PyPI: `memory.cpu` / `memory.gpu` (peak-footprint measurement), `models`
(the benchmarked problem builders), `report` and `bmf` (the artifact renderers). Pure Python,
built by hatchling, versioned off the same git tags as `monoprop`. It ships the console scripts
`monoprop-bench-report` and `monoprop-bench-bmf`. It contains **no benchmarks**.
(the benchmarked problem builders), `report` and `bmf` (the artifact renderers), and `rungs`
(the rung-table loader, runner and ladder collator). Pure Python, built by hatchling, versioned
off the same git tags as `monoprop`. It ships the console scripts `monoprop-bench-report`,
`monoprop-bench-bmf`, `monoprop-bench-rung` and `monoprop-bench-ladder`. It contains **no
benchmarks and no rung table** β€” those are data whose names campaigns already depend on.
- `packages/bench-third-party/` β€” cross-engine comparison scripts. Listed in the workspace
`exclude`: it pins a narrower `requires-python`, a git dependency and linux-x86_64-only CUDA
wheels, so it is a standalone uv project with its own `uv.lock`. Run it with
`cd packages/bench-third-party && uv sync`, never from the root environment.
- `benches/` β€” monoprop's own benchmark suite (`conftest.py`, `bench_*.py`, `results/`). It stays in
the repository and imports the tools package. Benchmark names are Bencher's history key, so they
must not move with a library release; that is why the suite is not in `monoprop-bench-tools`.
- `benches/` β€” monoprop's own benchmark suite (`conftest.py`, `bench_*.py`, `rungs.toml`,
`RUNGS.md`, `results/`). It stays in the repository and imports the tools package. Benchmark
names are Bencher's history key and rung ids name artifacts already written, so neither may move
with a library release; that is why the suite is not in `monoprop-bench-tools`.

Dependency groups follow from that split: `test` is monoprop's own suite only (cibuildwheel installs
it against a built wheel, so it must not reference a workspace member), `workspace-test` adds
Expand All @@ -83,7 +86,14 @@ Key files:
continuous-benchmarking workflow. Both read the schema written by `benches/conftest.py`, so a
change to the recorded sections has to land on both sides of the package boundary. Benchmark
names are Bencher's history key, so renaming or moving a `bench_*` test orphans its tracked
series.
series. Both bench modules measure the same four operations β€” `build_graph`, `propagate`,
`energy`, `gradient`.
- `benches/rungs.toml` and `monoprop_bench_tools.rungs`: the benchmark set at the sizes the
library is used at, as a table rather than a loop, so a campaign cannot quietly run a different
grid. Every row carries `expect_terms`, and a result missing it by >0.1% is refused: at a fixed
seed and tolerance the term count is reproducible to the digit, so the gate catches a mistyped
knob rather than tolerating noise. A row with `expect_terms = 0` has never been calibrated and
refuses to run. The scheduler that submits a rung is deliberately not in this repository.
- **`rounds > 1` overlaps two rounds' live memory** (`setup=` runs before the prior round's
teardown) β€” pin `--bench-rounds=1`; `record_memory` measures that construction transient,
not per-op cost (use `op_memory`).
Expand Down
44 changes: 41 additions & 3 deletions benches/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,58 @@ documentation for detailed instructions.
## What lives where

This directory holds only monoprop's own benchmarks β€” `conftest.py` (the fixtures
and the results schema), `bench_random.py`, `bench_models.py`, and `results/`.
and the results schema), `bench_random.py`, `bench_models.py`, `rungs.toml` (the
benchmark set), [`RUNGS.md`](RUNGS.md) (how to run it) and `results/`.

Both bench modules measure the same four operations β€” `build_graph`, `propagate`,
`energy` and `gradient` β€” so a number means the same thing whichever problem
produced it.

Benchmark names are the key [Bencher](https://bencher.dev/) stores history under,
so they stay here rather than moving with a library release.

Everything reusable is in the `monoprop-bench-tools` package
([`../packages/monoprop-bench-tools`](../packages/monoprop-bench-tools)): the
memory instrumentation, the model builders, and the two renderers that turn a
run's artifacts into `REPORT.md` and Bencher Metric Format JSON.
memory instrumentation, the model builders, the two renderers that turn a run's
artifacts into `REPORT.md` and Bencher Metric Format JSON, and the runner that
executes one row of `rungs.toml` and gates the result on its term count.

Cross-engine comparisons against other propagation libraries live in
[`../packages/bench-third-party`](../packages/bench-third-party), a standalone uv
project with its own lockfile.

## The rung ladder

`rungs.toml` is the benchmark set: one row per cell, giving the picture, the model,
the operations, the geometry, the size knobs and the exact term count that
configuration produces. A row, not a loop, so a campaign cannot quietly run a
different grid and two campaigns' numbers are comparable row for row.

```bash
monoprop-bench-rung benches/rungs.toml list # the set, and what each costs
monoprop-bench-rung benches/rungs.toml <id> --dry-run # the plan, no allocation spent
monoprop-bench-rung benches/rungs.toml <id> --rep 1 # one rep
monoprop-bench-ladder benches/rungs.toml benches/results # the block to paste into the PR
```

Nothing runs these for you. Run the rungs your change could plausibly move and put
the block in the pull request: it carries the timings, the peak memory, and the
resolved parameters of every problem measured.

`expect_terms` is a gate, not documentation: a result missing it by more than 0.1%
is refused, so a mistyped tolerance fails the cell instead of measuring a different
problem under the right name. A row nobody has calibrated says so twice --
`expect_terms = 0` and `TBD` on the unmeasured knob -- and refuses to run.

`cost_seconds` and `cost_gib_per_node` are the opposite: what one rep last cost, so
you can see what a rung takes before you spend it. Documentation, never a gate.
The machine and scheduler that run a rung are not in this repository; the table,
the runner and the gate are.

**[`RUNGS.md`](RUNGS.md)** is the guide: every model's parameters and what they do,
how the geometry maps onto a machine, example Slurm scripts, the pinning and
allocation-sizing traps, and how to calibrate a `TBD` row.

## Fixed-model sizing

At the default `--hubbard-lower-atol 1e-4`, both nominal Hubbard size axes are
Expand Down
Loading
Loading