parameterrun 0.4.1__tar.gz → 0.5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. parameterrun-0.5.0/.github/workflows/ci.yml +103 -0
  2. {parameterrun-0.4.1 → parameterrun-0.5.0}/.github/workflows/publish.yml +1 -1
  3. {parameterrun-0.4.1 → parameterrun-0.5.0}/.gitignore +18 -2
  4. parameterrun-0.5.0/CHANGELOG.md +136 -0
  5. parameterrun-0.5.0/PKG-INFO +447 -0
  6. parameterrun-0.5.0/README.md +414 -0
  7. parameterrun-0.5.0/dev/checkpointing_design.md +141 -0
  8. parameterrun-0.5.0/dev/distributed_shuffle.py +117 -0
  9. parameterrun-0.5.0/dev/profile_scalene.sh +30 -0
  10. parameterrun-0.5.0/dev/very_large_swap.py +27 -0
  11. parameterrun-0.5.0/docs/architecture.md +441 -0
  12. parameterrun-0.5.0/docs/checkpoints-and-shuffle.md +314 -0
  13. parameterrun-0.5.0/docs/github-actions.md +132 -0
  14. {parameterrun-0.4.1 → parameterrun-0.5.0}/examples/long_example.py +8 -2
  15. parameterrun-0.5.0/examples/minimal_example.py +19 -0
  16. {parameterrun-0.4.1 → parameterrun-0.5.0}/examples/minimal_example_mpi.py +2 -2
  17. {parameterrun-0.4.1 → parameterrun-0.5.0}/pyproject.toml +20 -8
  18. {parameterrun-0.4.1 → parameterrun-0.5.0}/scripts/bump_version.py +3 -13
  19. {parameterrun-0.4.1 → parameterrun-0.5.0}/src/parameterrun/__init__.py +1 -1
  20. parameterrun-0.5.0/src/parameterrun/_checkpoint.py +659 -0
  21. parameterrun-0.5.0/src/parameterrun/_delivery.py +118 -0
  22. parameterrun-0.5.0/src/parameterrun/_errors.py +158 -0
  23. parameterrun-0.5.0/src/parameterrun/_inputs.py +159 -0
  24. parameterrun-0.5.0/src/parameterrun/_joblib_backend.py +142 -0
  25. parameterrun-0.5.0/src/parameterrun/_mpi_dynamic.py +283 -0
  26. parameterrun-0.5.0/src/parameterrun/_mpi_static.py +509 -0
  27. parameterrun-0.5.0/src/parameterrun/_mpi_transfer.py +51 -0
  28. parameterrun-0.5.0/src/parameterrun/_progress.py +111 -0
  29. parameterrun-0.5.0/src/parameterrun/_pseudo_random.py +56 -0
  30. parameterrun-0.5.0/src/parameterrun/_results.py +60 -0
  31. parameterrun-0.5.0/src/parameterrun/_store.py +416 -0
  32. parameterrun-0.5.0/src/parameterrun/_utils.py +60 -0
  33. parameterrun-0.5.0/src/parameterrun/parallel_utils.py +447 -0
  34. parameterrun-0.5.0/src/parameterrun/py.typed +0 -0
  35. parameterrun-0.5.0/tests/test_checkpoint.py +659 -0
  36. parameterrun-0.5.0/tests/test_delivery.py +320 -0
  37. parameterrun-0.5.0/tests/test_depths.py +36 -0
  38. parameterrun-0.5.0/tests/test_dynamic_schedule.py +443 -0
  39. {parameterrun-0.4.1 → parameterrun-0.5.0}/tests/test_format_input.py +10 -11
  40. parameterrun-0.5.0/tests/test_get_iteration.py +11 -0
  41. parameterrun-0.5.0/tests/test_joblib.py +14 -0
  42. parameterrun-0.5.0/tests/test_mpi_integration.py +568 -0
  43. parameterrun-0.5.0/tests/test_mpi_rank_scaling.py +160 -0
  44. parameterrun-0.5.0/tests/test_normalized_time.py +13 -0
  45. parameterrun-0.5.0/tests/test_on_error.py +278 -0
  46. parameterrun-0.5.0/tests/test_parameter_run.py +243 -0
  47. {parameterrun-0.4.1 → parameterrun-0.5.0}/tests/test_pbar_format.py +29 -18
  48. parameterrun-0.5.0/tests/test_pbar_options.py +175 -0
  49. parameterrun-0.5.0/tests/test_pseudo_random.py +62 -0
  50. parameterrun-0.5.0/tests/test_result_checks.py +173 -0
  51. parameterrun-0.5.0/tests/test_review_regressions.py +490 -0
  52. parameterrun-0.4.1/.github/workflows/ci.yml +0 -65
  53. parameterrun-0.4.1/CHANGELOG.md +0 -72
  54. parameterrun-0.4.1/PKG-INFO +0 -289
  55. parameterrun-0.4.1/README.md +0 -257
  56. parameterrun-0.4.1/examples/minimal_example.py +0 -13
  57. parameterrun-0.4.1/src/parameterrun/parallel_utils.py +0 -494
  58. parameterrun-0.4.1/tests/test_depths.py +0 -36
  59. parameterrun-0.4.1/tests/test_get_iteration.py +0 -8
  60. parameterrun-0.4.1/tests/test_joblib.py +0 -14
  61. parameterrun-0.4.1/tests/test_mpi_integration.py +0 -30
  62. parameterrun-0.4.1/tests/test_normalized_time.py +0 -13
  63. parameterrun-0.4.1/tests/test_parameter_run.py +0 -136
  64. {parameterrun-0.4.1 → parameterrun-0.5.0}/.github/workflows/release.yml +0 -0
  65. {parameterrun-0.4.1 → parameterrun-0.5.0}/CONTRIBUTING.md +0 -0
  66. {parameterrun-0.4.1 → parameterrun-0.5.0}/LICENSE +0 -0
@@ -0,0 +1,103 @@
1
+ name: CI
2
+
3
+ on:
4
+ pull_request:
5
+ branches: [ main ]
6
+
7
+ permissions:
8
+ contents: read
9
+
10
+ jobs:
11
+ test:
12
+ name: non-mpi / ${{ matrix.os }} / py${{ matrix.python-version }}
13
+ runs-on: ${{ matrix.os }}
14
+ strategy:
15
+ fail-fast: false
16
+ matrix:
17
+ os: [ ubuntu-latest, macos-latest, windows-latest ]
18
+ python-version: [ "3.11", "3.12", "3.13", "3.14", "3.15" ]
19
+
20
+ steps:
21
+ - uses: actions/checkout@v6
22
+
23
+ - uses: actions/setup-python@v6
24
+ with:
25
+ python-version: ${{ matrix.python-version }}
26
+
27
+ - name: Install uv
28
+ run: python -m pip install uv
29
+
30
+ - name: Sync environment
31
+ run: uv sync
32
+
33
+ - name: Tests
34
+ run: uv run pytest -m "not mpi and not mpi_subprocess"
35
+
36
+ - name: Lint
37
+ run: uv run ruff check .
38
+
39
+ - name: Type check
40
+ run: uv run mypy
41
+
42
+ test-mpi:
43
+ name: mpi / ${{ matrix.os }} / ${{ matrix.mpi }} / py3.12 / 4+8 ranks
44
+ runs-on: ${{ matrix.os }}
45
+ env:
46
+ OMP_NUM_THREADS: "1"
47
+ OPENBLAS_NUM_THREADS: "1"
48
+ MKL_NUM_THREADS: "1"
49
+ strategy:
50
+ fail-fast: false
51
+ matrix:
52
+ include:
53
+ - os: ubuntu-latest
54
+ mpi: openmpi
55
+ - os: ubuntu-latest
56
+ mpi: mpich
57
+ - os: ubuntu-latest
58
+ mpi: intelmpi
59
+ - os: macos-latest
60
+ mpi: openmpi
61
+ - os: macos-latest
62
+ mpi: mpich
63
+ - os: windows-latest
64
+ mpi: msmpi
65
+ - os: windows-latest
66
+ mpi: intelmpi
67
+
68
+ steps:
69
+ - uses: actions/checkout@v6
70
+
71
+ - uses: actions/setup-python@v6
72
+ with:
73
+ python-version: "3.12"
74
+
75
+ - name: Setup MPI
76
+ uses: mpi4py/setup-mpi@v1
77
+ with:
78
+ mpi: ${{ matrix.mpi }}
79
+
80
+ - name: Install uv
81
+ run: python -m pip install uv
82
+
83
+ - name: Sync environment with MPI extra
84
+ run: uv sync --extra mpi
85
+
86
+ - name: Verify MPI runtime
87
+ env:
88
+ EXPECTED_MPI: ${{ matrix.mpi }}
89
+ run: >-
90
+ uv run python -c "import os; from mpi4py import MPI;
91
+ print(MPI.Get_library_version());
92
+ expected = {'openmpi': 'Open MPI', 'mpich': 'MPICH', 'intelmpi': 'Intel MPI', 'msmpi': 'Microsoft MPI'};
93
+ assert MPI.get_vendor()[0] == expected[os.environ['EXPECTED_MPI']], MPI.get_vendor()"
94
+
95
+ - name: MPI tests (4 ranks)
96
+ run: uv run mpiexec -n 4 python -m pytest -m mpi -o addopts="-q -m mpi"
97
+
98
+ - name: MPI scheduling and idle workers (8 ranks)
99
+ run: uv run mpiexec -n 8 python -m pytest tests/test_mpi_rank_scaling.py -m mpi -o addopts="-q -m mpi"
100
+
101
+ # Not under mpiexec: these tests start their own `mpiexec -n 4` (e.g. on_error="raise" must abort the job)
102
+ - name: MPI subprocess tests
103
+ run: uv run pytest -m mpi_subprocess -o addopts="-q -rs -m mpi_subprocess"
@@ -21,7 +21,7 @@ jobs:
21
21
 
22
22
  - uses: actions/setup-python@v6
23
23
  with:
24
- python-version: "3.9"
24
+ python-version: "3.11"
25
25
 
26
26
  - name: Install uv
27
27
  run: python -m pip install uv
@@ -186,7 +186,7 @@ cython_debug/
186
186
  # that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
187
187
  # and can be added to the global gitignore or merged into this file. However, if you prefer,
188
188
  # you could uncomment the following to ignore the entire vscode folder
189
- # .vscode/
189
+ .vscode/
190
190
 
191
191
  # Ruff stuff:
192
192
  .ruff_cache/
@@ -207,4 +207,20 @@ marimo/_lsp/
207
207
  __marimo__/
208
208
 
209
209
  # uv files
210
- uv.lock
210
+ uv.lock
211
+
212
+ # profile files
213
+ dev/profiles/*
214
+
215
+ # Claude
216
+ .claude/
217
+ CLAUDE.md
218
+
219
+ # Reports
220
+ reports/
221
+
222
+ # HPC benchmarks (local only)
223
+ HPC_test/
224
+
225
+ # Ferry ignore patterns
226
+ .ferryignore
@@ -0,0 +1,136 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file.
4
+
5
+ The format is based on Keep a Changelog and the project follows Semantic Versioning.
6
+
7
+ ## [0.5.0] - 2026-11-06
8
+
9
+ ### Added
10
+
11
+ - `shuffle_seed` parameter: seeds the permutation that distributes points among MPI ranks, making the distribution
12
+ reproducible. It was accepted by the MPI backend but never passed through. A keyword argument named `seed` is still
13
+ forwarded to the user function.
14
+ - `reshape="strict"` raises a `ValueError` when the result cannot be reshaped to the parameter grid.
15
+ - `RuntimeWarning` when some points return `None`, with the count and the parameters of the first one.
16
+ - `RuntimeWarning` when `backend="joblib"` with a negative `n_workers` runs inside an MPI job with more than one rank
17
+ (every rank would start a full-node pool).
18
+ - `on_error` parameter (`"raise"` by default, or `"nan"`) for exceptions raised by `fun`.
19
+ - `"raise"`: the exception keeps its type and gets the parameter values of the failing point as a note. Under MPI,
20
+ the failing rank prints the traceback once and calls `comm.Abort(1)`, instead of leaving the other ranks waiting
21
+ until the walltime limit.
22
+ - `"nan"`: failed points are filled with NaN of the right shape per output channel, and a `RuntimeWarning` reports
23
+ how many points failed and the traceback of the first one. If every point fails, a `RuntimeError` is raised.
24
+ - Dynamic MPI schedule (`mpi_schedule="dynamic"`): rank 0 becomes a manager that hands out chunks of points on demand,
25
+ and the other ranks compute. Fast ranks get more work, so the job no longer waits for the slowest rank. Numeric
26
+ outputs go straight into preallocated arrays on rank 0, the progress bar counts every point (not rank 0's share),
27
+ and with `on_error="raise"` the manager prints the failing point's traceback once and aborts the job. Results are
28
+ identical to the static schedule.
29
+ - `mpi_schedule` parameter: `"auto"` (default; dynamic with 8 ranks or more, static below), `"static"` or `"dynamic"`.
30
+ - `mpi_chunk_size` parameter: points per chunk for the dynamic schedule. The default (None) uses guided chunks that
31
+ shrink to one point at the end.
32
+ - `return_on` parameter: `"root"` (default), `"all"` (every MPI rank gets the result; numeric arrays are broadcast as
33
+ raw bytes, not pickled) or `"none"` (only the result file is written).
34
+ - `result_file` parameter: writes the result, reshaped to the grid, to a `.npy` file (one per output channel). Under
35
+ MPI, numeric outputs go into a memory-mapped file while the points arrive, so the result is no longer limited by
36
+ rank 0's memory.
37
+ - Checkpoints for long runs: `checkpoint` (a directory), `checkpoint_every` (points), `checkpoint_interval` (seconds,
38
+ 600 by default), `checkpoint_resume` (`"auto"`, `"force"`, `"restart"`) and `keep_checkpoint`. The finished points
39
+ are saved regularly, and calling `parameterrun` again with the same directory computes only the missing points, with
40
+ any backend, MPI schedule or number of ranks. Resuming checks the parameters, the extra keyword arguments and the code
41
+ of `fun` (bytecode, constants, defaults, closures, and helper functions of its module). The static MPI schedule
42
+ works in synchronised rounds between saves; the dynamic schedule saves without stopping the workers. `SIGUSR1`
43
+ saves at once (e.g. Slurm's `--signal=USR1@600`); `SIGTERM` saves, then ends the run. Snapshots are `.npz` files:
44
+ numeric outputs are stored without pickle, and outputs already in a memory-mapped `result_file` are not copied.
45
+
46
+ ### Changed
47
+
48
+ - `on_error`, `mpi_schedule`, `mpi_chunk_size`, `return_on`, `result_file` and the `checkpoint*` options are now
49
+ parameters of `parameterrun` itself, so keyword arguments with these names are no longer forwarded to `fun`.
50
+ - MPI, static schedule: results are no longer gathered as one pickled message per output channel. Numeric outputs are
51
+ sent as raw bytes in blocks of at most 64 MiB straight into preallocated arrays on rank 0. This removes the 2 GB
52
+ limit of pickled messages (`MPI_ERR_ARG` on large results) and most of rank 0's extra copies; non-numeric outputs
53
+ are still pickled. Both schedules now share this result store, so they return the same arrays.
54
+ - MPI: every call uses its own duplicated communicator, so messages of one call can never reach another.
55
+ - MPI runs with 8 ranks or more now use the dynamic schedule by default, which leaves rank 0 to the manager. Pass
56
+ `mpi_schedule="static"` for the previous behaviour.
57
+ - `backend=None` now falls back to joblib when `mpi4py` is installed but no MPI library is found, instead of failing
58
+ with `RuntimeError: cannot load MPI library`. `backend="mpi"` raises an `ImportError` that names the missing library.
59
+ - **Breaking:** dropped support for Python 3.9 and 3.10; `parameterrun` now requires Python >= 3.11.
60
+ - Added support for Python 3.13, 3.14 and 3.15 (classifiers and CI test matrix).
61
+ - A failed reshape now emits a `RuntimeWarning` that explains why, instead of printing "Could not reshape the result".
62
+ - `pbar_bool` now defaults to `None`: progress bars are shown on a terminal or in a notebook, hidden otherwise, and
63
+ `TQDM_DISABLE` is honoured. Forced bars on a non-terminal output (e.g. Slurm logs) print one plain line per refresh,
64
+ every 30 s by default (`TQDM_MININTERVAL` overrides it).
65
+ - MPI: rank 0 now waits for the workers with a blocking receive instead of a busy `Iprobe` loop.
66
+ - MPI: results are sorted with `np.argsort` instead of Python's `sorted`.
67
+
68
+ ### Removed
69
+
70
+ - The Open MPI 5.0.6 version-string workaround for the progress bar. Bars on MPI ranks whose stdout is a terminal now
71
+ end each refresh with a newline, so MPI launchers that forward output line by line show them with any MPI version.
72
+
73
+ ## [0.4.1] - 2026-04-21
74
+
75
+ ### Fixed
76
+
77
+ - Fix the display of the progress bar when running with `backend="joblib"`, since the previous implementation didn't
78
+ have access to the total number of runs to compute, which is required for the progress bar to work properly.
79
+
80
+ ### Added
81
+
82
+ - Added a test for the progress bar display when running with `backend="joblib"`.
83
+
84
+ ## [0.4.0] - 2026-04-21
85
+
86
+ ### Added
87
+
88
+ - Added `tests/test_mpi_integration.py` with MPI numerical-equivalence coverage for `parameterrun(..., backend="mpi")`.
89
+ - Added a dedicated Linux PR CI job that runs MPI tests with 4 ranks.
90
+
91
+ ### Changed
92
+
93
+ - Updated default test commands in docs and CI to run non-MPI tests with `-m "not mpi"`.
94
+ - Registered a pytest `mpi` marker in `pyproject.toml` for explicit MPI test selection.
95
+ - Update how the indices to compute are shared among workers. Previously, all the indices where computed by all workers,
96
+ which caused a significan overhead in the memory usage. Now, the indices are computed on the fly.
97
+
98
+ ## [0.3.0] - 2026-04-01
99
+
100
+ ### Changed
101
+
102
+ - Added `result_as_array` to `parameterrun(...)`: outputs are numpy arrays by default and can be converted to Python
103
+ lists with `result_as_array=False`.
104
+ - Removed the `pbar_kwargs` optional argument from `parameterrun(...)`, as it was unused.
105
+ - Added more tests for the depth of the parameter grid.
106
+ - Added the possibility to add parameter values as numpy arrays, which are converted to lists internally.
107
+
108
+ ## [0.2.1] - 2026-04-01
109
+
110
+ ### Added
111
+
112
+ - Modified GitHub Actions workflow to trigger on pull requests to the main branch, ensuring that all changes are
113
+ reviewed before merging.
114
+
115
+ ## [0.2.0] - 2026-03-26
116
+
117
+ ### Added
118
+
119
+ - Automated version management: single source of truth in `src/parameterrun/__init__.py`
120
+ - Version bump script `scripts/bump_version.py` for automatic version updates across all files
121
+ - VERSIONING.md guide for release workflows and version management
122
+ - `__version__` exported from main package: `from parameterrun import __version__`
123
+ - Dynamic version extraction in `pyproject.toml` (no more manual version updates needed)
124
+
125
+ ### Changed
126
+
127
+ - `parameterrun(..., reshape=True)` now reshapes outputs to the parameter-grid dimensions automatically (including
128
+ multi-output functions).
129
+ - Added early validation for duplicate parameter names, unknown swept parameters, unknown kwargs, and kwarg/sweep-name
130
+ conflicts.
131
+
132
+ ## [0.1.0] - 2026-03-25
133
+
134
+ ### Added
135
+
136
+ - Initial public release of `parameterrun`