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
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,17 @@

## [Unreleased]

### Fixed
- `hypyp.sync`: asking for the Metal backend on a metric that has no Metal kernel (PLV, CCorr, Coh, ImCoh, EnvCorr, PowCorr) used to run in NumPy silently, while the metric object reported `metal`. The computation still runs in NumPy, so no computed value changes, but it now warns and the metric object reports `numpy`. This holds for `optimization='metal'` and for a `priority` list that reaches Metal on a machine where Metal is available: the backends that follow in the list are not tried, which is left to 0.7.0. Only PLI, wPLI and ACCorr have a Metal kernel; the default selection of `optimization='auto'` is unchanged for the nine built-in metrics (#299)
- `hypyp.sync`: when a backend of a `priority` list can neither run on the machine nor be computed by the metric, and no other GPU backend of the list can be used, the warning now says so (for example "'plv' has no Metal implementation") instead of "No GPU backend available"
- `hypyp.sync`: a metric whose `_backend` was set to a backend it does not implement used to compute in NumPy without notice. It still computes in NumPy, now with a warning. A `_backend` that is not the name of a backend raises a `ValueError` naming the metric and the backends it implements; called through `compute_sync`, that error is still reworded as an unsupported metric (#306)
- Tests: the six Metal tests that compared NumPy with NumPy are replaced by tests of the fallback itself (warning, backend and result), the dispatch of every metric to every backend it implements is checked without a GPU, and the four tests that run a Metal kernel now assert that the Metal method was called (#300)

### Added
- `BaseMetric.supports(backend)` tells whether a metric implements a backend, for example `PLI.supports('metal')`

### Changed
- `hypyp.sync`: backend dispatch now lives in `BaseMetric.compute`, and each built-in metric implements `_compute_numpy` plus the optional `_compute_numba`, `_compute_torch`, `_compute_metal` and `_compute_cuda`. This is the recommended way to write a new metric: set `_dispatch_via_table = True` in the class. A subclass written the earlier way, which overrides `compute` and does its own dispatch, is still granted the backend it requests and is not subject to the capability check, whether it derives from `BaseMetric` or from a built-in metric. A subclass of a built-in metric that overrides `compute` and delegates to `super().compute()` keeps the earlier results: a backend without a `_compute_*` method computes in NumPy, now with a warning, and the CPU fallback of `optimization='auto'` still selects numba for it when numba is installed. A `_compute_*` method that a subclass adds for a backend its parent does not implement was never called before and is still not, unless the subclass sets `_dispatch_via_table = True` itself; a method of the parent that the subclass overrides is used, as before
- The whole code base is formatted with `ruff format` (line length 88). The change is purely cosmetic: the syntax tree of every file is unchanged, apart from whitespace inside docstrings, and the Python examples of `hypyp/sync/README.md` are formatted too. The vendored `hypyp/ext` and the tutorial notebooks are left untouched. The formatting commit is listed in `.git-blame-ignore-revs`, so `git blame` skips it (run `git config blame.ignoreRevsFile .git-blame-ignore-revs` once in your clone; GitHub applies it automatically)
- The CI now checks formatting (`ruff format --check`) and a small set of lint rules that only catch certain bugs: syntax errors, invalid comparisons and undefined names. Ruff comes from the new `lint` dependency group, which the `dev` group includes
- `black` is removed from the `dev` dependency group, since `ruff format` replaces it
Expand Down
4 changes: 2 additions & 2 deletions hypyp/sync/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
Public API
----------
``BaseMetric``
Abstract base class. Concrete metrics inherit from it and implement
``BaseMetric.compute``.
Base class. Concrete metrics inherit from it and implement
``_compute_numpy`` plus the optional accelerated ``_compute_*`` methods.

Concrete metric classes (one per file):

Expand Down
12 changes: 2 additions & 10 deletions hypyp/sync/accorr.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ class ACCorr(BaseMetric):
"""

name = "accorr"
_dispatch_via_table = True

def __init__(
self,
Expand Down Expand Up @@ -109,16 +110,7 @@ def compute(
con : np.ndarray
ACCorr connectivity matrix with shape (n_epoch, n_freq, 2*n_ch, 2*n_ch).
"""
if self._backend == "metal":
return self._compute_metal(complex_signal, n_samp, transpose_axes)
elif self._backend == "cuda_kernel":
return self._compute_cuda(complex_signal, n_samp, transpose_axes)
elif self._backend == "numba":
return self._compute_numba(complex_signal, n_samp, transpose_axes)
elif self._backend == "torch":
return self._compute_torch(complex_signal, n_samp, transpose_axes)
else:
return self._compute_numpy(complex_signal, n_samp, transpose_axes)
return super().compute(complex_signal, n_samp, transpose_axes)

def _compute_metal(
self, complex_signal: np.ndarray, n_samp: int, transpose_axes: tuple
Expand Down
Loading
Loading