Skip to content

Commit 38fd31d

Browse files
authored
Add CuPy support to ArrayStore via Array API (#579)
## Description <!-- Provide a brief description of the PR's purpose here. --> This PR supports CuPy via the Array API. At first I thought this might be challenging since CuPy has a different model of devices, i.e., it depends on context managers rather than passing in devices. However, array-api-compat seems to have solved these issues and made CuPy compatible in terms of devices. Here are some references that I looked at: - data-apis/array-api-compat#293 - https://github.com/data-apis/array-api-compat/blob/main/array_api_compat/cupy/_aliases.py - https://docs.cupy.dev/en/stable/reference/array_api_functions.html#cupy.array_api.ones ## TODO <!-- Notable points that this PR has either accomplished or will accomplish. --> - [x] Add cupy backend to conftest - [x] Add instructions for installing cupy - [x] Test ArrayStore with CuPy on GPU - [x] Update ArrayStore to consider CuPy in pandas return type - [x] Add cupy tests to CI -- I installed CuPy but the CuPy tests won't actually run because we don't have a GPU runner set up -- following scipy (https://github.com/scipy/scipy/blob/main/.github/workflows/gpu-ci.yml), I also set the CI to only run on ubuntu, since installing cupy on mac and windows seems to be problematic ## Status - [x] I have read the guidelines in [CONTRIBUTING.md](https://github.com/icaros-usc/pyribs/blob/master/CONTRIBUTING.md) - [x] I have formatted my code using `yapf` - [x] I have tested my code by running `pytest` - [x] I have linted my code with `pylint` - [x] I have added a one-line description of my change to the changelog in `HISTORY.md` - [x] This PR is ready to go
1 parent c4f9ebe commit 38fd31d

File tree

5 files changed

+33
-7
lines changed

5 files changed

+33
-7
lines changed

.github/workflows/testing.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ jobs:
6565
strategy:
6666
max-parallel: 12 # All in parallel.
6767
matrix:
68-
os: [ubuntu-latest, macos-latest, windows-latest]
68+
os: [ubuntu-latest]
6969
python-version: ["3.12"]
7070
runs-on: ${{ matrix.os }}
7171
steps:
@@ -77,6 +77,8 @@ jobs:
7777
run: pip install .[dev]
7878
- name: Install torch
7979
run: pip install torch
80+
- name: Install cupy
81+
run: pip install cupy-cuda12x
8082
- name: Test core
8183
run: >
8284
pytest tests/archives tests/emitters tests/schedulers

HISTORY.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
#### API
88

9-
- Support array backends via Python array API Standard ({pr}`573`, {pr}`571`)
9+
- Support array backends via Python array API Standard ({issue}`570`)
1010
- **Backwards-incompatible:** Remove raw_dict methods from ArrayStore
1111
({pr}`575`)
1212

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,10 +124,11 @@ python -c "import ribs; print(ribs.__version__)"
124124
You should see a version number in the output.
125125

126126
**Experimental:** Pyribs is experimenting with adding support for running QD
127-
algorithms in PyTorch via the
127+
algorithms in PyTorch and CuPy via the
128128
[Python array API standard](https://data-apis.org/array-api/latest/). To enable
129-
this functionality, [install PyTorch](https://pytorch.org), such as with
130-
`pip install torch`.
129+
this functionality, install [PyTorch](https://pytorch.org), such as with
130+
`pip install torch`, and [CuPy](https://cupy.dev), such as with
131+
`pip install cupy-cuda12x`.
131132

132133
## Usage
133134

ribs/archives/_array_store.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,13 @@
44
from enum import IntEnum
55
from functools import cached_property
66

7-
from array_api_compat import is_numpy_array, is_numpy_namespace, is_torch_array
7+
from array_api_compat import (is_cupy_array, is_numpy_array, is_numpy_namespace,
8+
is_torch_array)
9+
10+
try:
11+
from array_api_compat import cupy as cp
12+
except ImportError:
13+
pass
814

915
from ribs._utils import arr_readonly, xp_namespace
1016
from ribs.archives._archive_data_frame import ArchiveDataFrame
@@ -292,10 +298,12 @@ def _convert_to_numpy(arr):
292298
return arr
293299
elif is_torch_array(arr):
294300
return arr.cpu().detach().numpy()
301+
elif is_cupy_array(arr):
302+
return cp.asnumpy(arr)
295303
else:
296304
raise NotImplementedError(
297305
"The pandas return type is currently only supported "
298-
"with numpy and torch arrays.")
306+
"with NumPy, PyTorch, and CuPy arrays.")
299307

300308
def retrieve(self, indices, fields=None, return_type="dict"):
301309
"""Collects data at the given indices.

tests/conftest.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,21 @@
2424
except ImportError:
2525
pass
2626

27+
try:
28+
import cupy as cp
29+
from cupy_backends.cuda.api.runtime import CUDARuntimeError
30+
31+
cp.empty(0) # Triggers CUDARuntimeError if there is no GPU available.
32+
33+
xp_available_backends.append(
34+
pytest.param((cp, cp.cuda.Device(0)), id="cupy-gpu"))
35+
except ImportError:
36+
# CuPy not installed.
37+
pass
38+
except CUDARuntimeError:
39+
# GPU not available.
40+
pass
41+
2742

2843
@pytest.fixture(params=xp_available_backends)
2944
def xp_and_device(request):

0 commit comments

Comments
 (0)