CuPy backend#
CuPy is a near drop-in replacement for NumPy that runs on NVIDIA GPUs via CUDA. Use it when you want GPU acceleration for array-API operations and you don’t need JAX autodiff/JIT.
Installation#
pip install brainunit[cupy]
Requires a working CUDA toolkit; the cupy-cuda12x wheel is pulled in by
the extra. If you have CUDA 11, install cupy-cuda11x manually instead.
Graceful import#
If CuPy isn’t installed (most CI runners and laptops without an NVIDIA GPU), the snippets below skip cleanly rather than crashing.
import brainunit as u
try:
import cupy
HAVE_CUPY = True
runtime = cupy.cuda.runtime
device_id = runtime.getDevice()
device_name = runtime.getDeviceProperties(device_id)['name']
if isinstance(device_name, bytes):
device_name = device_name.decode()
except ImportError:
HAVE_CUPY = False
print('cupy not installed; install with: pip install brainunit[cupy]')
if HAVE_CUPY:
print('CuPy version:', cupy.__version__)
print('CUDA devices:', runtime.getDeviceCount())
print('CUDA driver/runtime:', runtime.driverGetVersion(), '/', runtime.runtimeGetVersion())
print('GPU:', device_name)
print('is_cupy_array on a non-cupy object:', u.is_cupy_array([1, 2, 3]))
CuPy version: 14.1.1
CUDA devices: 1
CUDA driver/runtime: 13030 / 12090
GPU: NVIDIA GeForce RTX 3060 Laptop GPU
is_cupy_array on a non-cupy object: False
Quick start#
if HAVE_CUPY:
q = u.Quantity(cupy.array([1.0, 2.0, 3.0]), unit=u.meter)
print(q)
print('backend =', q.backend)
print('(q + q).backend =', (q + q).backend)
[1. 2. 3.] m
backend = cupy
(q + q).backend = cupy
Math operations#
brainunit.math dispatches to array_api_compat.cupy, executing on the GPU.
if HAVE_CUPY:
x = u.Quantity(cupy.linspace(0.0, cupy.pi, 5), unit=u.UNITLESS)
print(u.math.sin(x))
[0.00000000e+00 7.07106781e-01 1.00000000e+00 7.07106781e-01
1.22464680e-16]
Converting between backends#
Quantity.to_cupy(device=...) moves the mantissa to the chosen GPU.
if HAVE_CUPY:
import numpy as np
q_cpu = u.Quantity(np.array([1.0, 2.0]), unit=u.meter)
q_gpu = q_cpu.to_cupy(device=0)
print('mantissa lives on device', q_gpu.mantissa.device)
# round-trip back to NumPy
print(q_gpu.to_numpy())
mantissa lives on device <CUDA Device 0>
[1. 2.] m
Requesting the backend explicitly#
If you ask for the CuPy backend when CuPy isn’t installed, brainunit raises
BackendError (not a bare ImportError) with the install hint.
When CuPy or a usable CUDA device is unavailable, explicitly
selecting the backend raises a BackendError with the installation hint:
from brainunit import BackendError
try:
with u.using_backend('cupy'):
u.Quantity([1.0, 2.0], unit=u.meter)
except BackendError as exc:
print(exc)
Limitations#
CuPy has no autograd.
brainunit.autogradis JAX-only.brainunit.laxandbrainunit.sparseare JAX-only.Move data to NumPy or JAX with
.to_numpy()/.to_jax()for those.