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
16 changes: 15 additions & 1 deletion .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ variables:
PIP_DISABLE_PIP_VERSION_CHECK: "1"
CUNUMPY_BACKEND: "cupy"
CUNUMPY_REQUIRE_CUDA: "1"
# empty: the newest CuPy; gpu_tests_min_cupy pins the oldest supported one
CUPY_PIN: ""

stages:
- test
Expand All @@ -19,7 +21,7 @@ stages:
- module load fftw-serial/3.3.10
- nvidia-smi
# Keep NVRTC, CUDA libraries and headers on the same toolkit generation.
- python3 -m pip install --user "cupy-cuda13x[ctk]" "cuda-toolkit==13.2.*"
- python3 -m pip install --user "cupy-cuda13x[ctk]${CUPY_PIN}" "cuda-toolkit==13.2.*"
- python3 -m pip install --user -e ".[test]"
- export PATH="$HOME/.local/bin:$PATH"
- python3 -c "import cupy; cupy.show_config()"
Expand All @@ -28,6 +30,18 @@ gpu_tests:
extends: .gpu_job
script:
- python3 -m pytest -q tests
- python3 testing/cupyx_names.py

# The oldest supported CuPy (cunumpy.MIN_CUPY_VERSION): the whole suite, and the
# fake cupyx.scipy must list exactly its names (_fake_cupyx.NAMES).
gpu_tests_min_cupy:
extends: .gpu_job
variables:
CUPY_PIN: "==14.0.0"
script:
- python3 -c "import cupy, cunumpy; assert cupy.__version__ == cunumpy.MIN_CUPY_VERSION, cupy.__version__"
- python3 -m pytest -q tests
- python3 testing/cupyx_names.py --exact

gpu_sanitizers:
extends: .gpu_job
Expand Down
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]

### Added
- Supported CuPy versions: 14.0 or newer (`xp.MIN_CUPY_VERSION`,
`xp.cupy_version_supported`); an older CuPy warns when the CuPy backend is
first checked, and `backend_info()` reports the minimum. The GPU CI runs the
whole suite on CuPy 14.0.0 too (`gpu_tests_min_cupy`).
- MIT license (`LICENSE.txt`, referenced by `pyproject.toml`).
- `xp.optimize.newton`: Newton's method or the secant method on many
independent scalar equations at once, with the steps of
Expand All @@ -16,7 +20,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- The fake CuPy has `cupyx.scipy`: SciPy behind the CuPy rules (host arrays
rejected, fake device arrays and proxy objects returned), so `xp.scipy` code
runs its CuPy path without a GPU. Every `cupyx.scipy` subpackage has only
the names CuPy v14.2.0 provides, so e.g. `special.jv` fails as on a GPU.
the names the oldest supported CuPy (14.0.0) provides, so e.g. `special.jv`
or `sparse.csr_array` fails as on a GPU. `testing/cupyx_names.py` and
`tests/unit/test_cupyx_names.py` check these names against the installed
CuPy in the GPU CI.
`cupyx.empty_pinned`/`zeros_pinned` return NumPy arrays.
- `xp.optimize.fsolve`, `root`, `minimize` and `xp.integrate.quad`, `odeint`
(`cupyx.scipy` has neither): SciPy on the host with SciPy's arguments, the
Expand Down
4 changes: 3 additions & 1 deletion docs/source/guides/solvers.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ def periodic_poisson(rho, length):
`xp.scipy.special` on both backends.
* On the fake CuPy (tests without a GPU), `xp.scipy` runs SciPy with the CuPy
rules: host arrays are rejected, results are fake device arrays, and each
subpackage has only the names CuPy has.
subpackage has only the names of the oldest supported CuPy
(`xp.MIN_CUPY_VERSION`), so code that passes there runs on every supported
CuPy.

## Splines and interpolation

Expand Down
7 changes: 7 additions & 0 deletions docs/source/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,15 @@ example:

```bash
python -m pip install cupy-cuda12x # CUDA 12.x
python -m pip install cupy-cuda13x # CUDA 13.x
```

CuNumpy supports CuPy 14.0 or newer (`xp.MIN_CUPY_VERSION`); the GPU CI tests
14.0 and the newest release. CuPy 13 lacks parts of `cupyx.scipy` that
CuNumpy relies on (`interpolate.UnivariateSpline`, `NdBSpline`,
`CubicSpline`, ...): selecting the CuPy backend with an older CuPy warns.
`xp.backend_info()` shows the installed and the minimum version.

On HPC clusters, load the site's CUDA module first and check the CuPy
installation guide for the matching package name. Then verify that CuNumpy can
use it:
Expand Down
1 change: 1 addition & 0 deletions docs/source/reference/top-level.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ The NumPy/CuPy namespace (see the [API overview](../api.md)) plus backend select

```{eval-rst}
.. autodata:: cunumpy.scipy
.. autodata:: cunumpy.MIN_CUPY_VERSION
```
4 changes: 4 additions & 0 deletions src/cunumpy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,12 @@
from cunumpy._scipy_backend import scipy
from cunumpy._staging import to_host_async
from cunumpy.xp import (
MIN_CUPY_VERSION,
as_device_array,
assert_same_backend,
backend_info,
cupy_available,
cupy_version_supported,
default_float_dtype,
get_array_backend,
get_array_module,
Expand Down Expand Up @@ -96,6 +98,7 @@ def require_version(minimum: str) -> None:


__all__ = [
"MIN_CUPY_VERSION",
"__version__",
"algorithms",
"arguments",
Expand All @@ -105,6 +108,7 @@ def require_version(minimum: str) -> None:
"cuda",
"cupy_available",
"cupy_backend",
"cupy_version_supported",
"default_float_dtype",
"evaluate_on_host",
"get_array_backend",
Expand Down
4 changes: 4 additions & 0 deletions src/cunumpy/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ def to_cupy(array: Any) -> Any: ...
def to_cunumpy(array: Any) -> Any: ...
def to_host_async(array: Any) -> HostCopy: ...
def cupy_available() -> bool: ...
def cupy_version_supported(cupy_version: str) -> bool: ...

MIN_CUPY_VERSION: str

def backend_info() -> dict[str, Any]: ...
def get_array_module(array: Any) -> Any: ...
def get_backend() -> str: ...
Expand Down
Loading
Loading