Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

backends

backends

Backend abstraction for CPU/GPU operations.

Supports NumPy (CPU-only) and PyTorch (CPU/CUDA/MPS) backends for linear algebra operations. Enables transparent acceleration while maintaining NumPy-first development.

Attributes:

NameTypeDescription
BATCH_WORKING_SET_CEILING_GB

Classes:

NameDescription
BackendBackend abstraction for numerical operations.

Methods:

NameDescription
assert_array_almost_equalTest array equality with automatic precision adjustment for MPS backend.
auto_batch_sizeSplit n_items into batches that fit a memory budget.
auto_n_jobs_for_arraysMemory-aware joblib worker count for a per-item map over arrays.
auto_select_backendAutomatically select backend based on problem size.
check_gpu_availableCheck if GPU acceleration is available.
compute_oom_safeRun fn(*arrays) with reactive out-of-memory recovery.
device_memory_budgetUsable memory budget in GB for a backend’s device.
empty_device_cacheRelease cached device memory. No-op without torch or a GPU.
gb_to_bytesConvert a GB budget to bytes — the package’s one GB↔bytes conversion.
is_oom_errorTrue if exc is a device out-of-memory error (CUDA or MPS).
resolve_backendCoerce a backend specifier into a Backend instance.

Classes

Backend

Backend(backend: str = 'numpy')

Backend abstraction for numerical operations.

Provides a unified interface for NumPy and PyTorch operations, enabling transparent GPU acceleration when available.

Parameters:

NameTypeDescriptionDefault
backendstrBackend type: ‘numpy’, ‘torch’, or ‘auto’ - ‘numpy’: CPU-only using NumPy - ‘torch’: PyTorch with automatic device detection (cuda/mps/cpu) - ‘auto’: Automatically select best available backend‘numpy’

Attributes:

NameTypeDescription
namestrBackend identifier (e.g., ‘numpy’, ‘torch-cuda’, ‘torch-mps’)
devicestrDevice type (‘cpu’, ‘cuda’, or ‘mps’)
xpmoduleArray library module (numpy or torch)

Methods:

NameDescription
asarrayConvert input to a backend array.
asarray_likeConvert x to an array matching ref’s dtype (and device for torch).
check_arraysCoerce all inputs to the same dtype (and device) as the first.
concatenateConcatenate arrays along an axis.
copyReturn an independent copy of the array.
dtype_to_strNormalize a dtype (numpy, torch, or string) to its string name.
expand_dimsInsert a new axis.
flatnonzeroReturn indices of non-zero elements in the flattened array.
fullCreate array filled with fill_value.
full_likeCreate array filled with fill_value, optionally with a different shape.
matmulMatrix multiplication.
ones_likeCreate ones array, optionally with a different shape.
sortSort along an axis, returning values only.
svdCompute Singular Value Decomposition.
to_cpuTransfer array to CPU. No-op for numpy.
to_deviceTransfer array to backend device.
to_gpuTransfer array to GPU. No-op for numpy.
to_numpyConvert array back to NumPy.
zeros_likeCreate zeros array, optionally with a different shape.

Methods

asarray
asarray(x, dtype = None, device = None)

Convert input to a backend array.

Handles numpy arrays, lists, and torch tensors. Places result on the backend’s device (or an explicit device).

Parameters:

NameTypeDescriptionDefault
xInput data (array-like, tensor, list).required
dtypeDesired dtype as string, numpy, or torch dtype. If None, inferred from input.None
deviceTarget device string (e.g. “cpu”, “cuda”). Ignored for numpy backend. If None, uses the backend’s default device.None

Returns:

TypeDescription
Backend array (numpy ndarray or torch Tensor).
asarray_like
asarray_like(x, ref)

Convert x to an array matching ref’s dtype (and device for torch).

Parameters:

NameTypeDescriptionDefault
xInput data.required
refReference array whose dtype/device to match.required

Returns:

TypeDescription
Backend array with same dtype/device as ref.
check_arrays
check_arrays(*inputs)

Coerce all inputs to the same dtype (and device) as the first.

None values are passed through. Lists of arrays are converted element-wise.

Parameters:

NameTypeDescriptionDefault
*inputsArrays, lists of arrays, or None.()

Returns:

NameTypeDescription
listConverted arrays in the same order as inputs.
concatenate
concatenate(arrays, axis = 0)

Concatenate arrays along an axis.

Parameters:

NameTypeDescriptionDefault
arraysSequence of arrays.required
axisAxis to concatenate along (default 0).0
copy
copy(array)

Return an independent copy of the array.

Parameters:

NameTypeDescriptionDefault
arrayInput array.required
dtype_to_str
dtype_to_str(dtype)

Normalize a dtype (numpy, torch, or string) to its string name.

Parameters:

NameTypeDescriptionDefault
dtypeData type to convert (str, numpy dtype, torch dtype, or None).required

Returns:

TypeDescription
str or None: e.g. “float32”, “float64”, or None if input was None.
expand_dims
expand_dims(array, axis)

Insert a new axis.

Parameters:

NameTypeDescriptionDefault
arrayInput array.required
axisPosition of the new axis.required
flatnonzero
flatnonzero(array)

Return indices of non-zero elements in the flattened array.

Parameters:

NameTypeDescriptionDefault
arrayInput array.required
full
full(shape, fill_value, dtype = None)

Create array filled with fill_value.

Parameters:

NameTypeDescriptionDefault
shapeOutput shape (int or tuple).required
fill_valueScalar fill value.required
dtypeOutput dtype. If None, inferred by the backend.None
full_like
full_like(array, fill_value, shape = None, dtype = None, device = None)

Create array filled with fill_value, optionally with a different shape.

Parameters:

NameTypeDescriptionDefault
arrayReference array for dtype inference.required
fill_valueScalar fill value.required
shapeOutput shape. If None, uses array.shape.None
dtypeOutput dtype. If None, uses array.dtype.None
deviceTarget device (torch only). If None, uses array’s device.None
matmul
matmul(A, B)

Matrix multiplication.

Parameters:

NameTypeDescriptionDefault
AarrayFirst matrixrequired
BarraySecond matrixrequired

Returns:

NameTypeDescription
arrayResult of A @ B
ones_like
ones_like(array, shape = None, dtype = None, device = None)

Create ones array, optionally with a different shape.

Parameters:

NameTypeDescriptionDefault
arrayReference array for dtype inference.required
shapeOutput shape. If None, uses array.shape.None
dtypeOutput dtype. If None, uses array.dtype.None
deviceTarget device (torch only). If None, uses array’s device.None
sort
sort(array, axis = -1)

Sort along an axis, returning values only.

Parameters:

NameTypeDescriptionDefault
arrayInput array.required
axisAxis to sort along (default -1).-1
svd
svd(X, full_matrices = False)

Compute Singular Value Decomposition.

Parameters:

NameTypeDescriptionDefault
XarrayInput matrix (n_samples, n_features)required
full_matricesbool, default=FalseIf False, returns reduced SVDFalse

Returns:

NameTypeDescription
tuple(U, s, Vt) where: - U (array): Left singular vectors - s (array): Singular values - Vt (array): Right singular vectors (transposed)
to_cpu
to_cpu(array)

Transfer array to CPU. No-op for numpy.

Parameters:

NameTypeDescriptionDefault
arrayInput array or tensor.required

Returns:

TypeDescription
Array on CPU.
to_device
to_device(arr: np.ndarray)

Transfer array to backend device.

Parameters:

NameTypeDescriptionDefault
arrndarrayInput numpy arrayrequired

Returns:

NameTypeDescription
arrayArray on device (numpy array or torch tensor)
to_gpu
to_gpu(array, device = None)

Transfer array to GPU. No-op for numpy.

Parameters:

NameTypeDescriptionDefault
arrayInput array or tensor.required
deviceTarget device (defaults to backend’s device).None

Returns:

TypeDescription
Array on GPU device.
to_numpy
to_numpy(arr)

Convert array back to NumPy.

Parameters:

NameTypeDescriptionDefault
arrndarray or TensorArray to convertrequired

Returns:

TypeDescription
np.ndarray: NumPy array
zeros_like
zeros_like(array, shape = None, dtype = None, device = None)

Create zeros array, optionally with a different shape.

Parameters:

NameTypeDescriptionDefault
arrayReference array for dtype inference.required
shapeOutput shape. If None, uses array.shape.None
dtypeOutput dtype. If None, uses array.dtype.None
deviceTarget device (torch only). If None, uses array’s device.None

Methods

assert_array_almost_equal

assert_array_almost_equal(x, y, decimal = 6, err_msg = '', verbose = True, backend = None)

Test array equality with automatic precision adjustment for MPS backend.

This utility automatically reduces precision expectations for torch-mps backend due to float32 precision limitations, preventing test failures while maintaining realistic precision checks for other backends.

Parameters:

NameTypeDescriptionDefault
xFirst array to comparerequired
ySecond array to comparerequired
decimalDesired decimal precision (default: 6)6
err_msgError message prefix‘’
verboseWhether to print detailed error messagesTrue
backendBackend instance (optional). If None, attempts to detect from x/y.None

Returns:

TypeDescription
None (raises AssertionError if arrays don’t match)

auto_batch_size

auto_batch_size(n_items: int, bytes_per_item: float, *, budget_gb: float, overhead: float = 1.0, min_batch: int = 1) -> tuple[int, int]

Split n_items into batches that fit a memory budget.

The one batch calculator for the package. Callers supply only the per-item working-set estimate (bytes_per_item) and an algorithm’s allocation overhead factor; the clamp/ceil policy lives here.

Parameters:

NameTypeDescriptionDefault
n_itemsintTotal number of items (permutations, targets, ...).required
bytes_per_itemfloatDominant working-set size of one item in bytes.required
budget_gbfloatMemory budget from device_memory_budget.required
overheadfloatMultiplier for intermediate allocations (e.g. 3.0 when the computation holds ~3x the input working set).1.0
min_batchintSmallest batch worth dispatching (amortizes launch and transfer overhead). Never exceeds n_items.1

Returns:

TypeDescription
inttuple[int, int]: (batch_size, n_batches) with
intbatch_size * n_batches >= n_items.

auto_n_jobs_for_arrays

auto_n_jobs_for_arrays(arrays, *, max_memory_gb: float | None = None, min_jobs: int = 1) -> int

Memory-aware joblib worker count for a per-item map over arrays.

Sizes workers by the largest item (each worker pickles its item), using the same measured budget as the device batching layer. None entries are ignored; an empty list returns min_jobs.

Parameters:

NameTypeDescriptionDefault
arraysIterable of numpy arrays (None entries allowed).required
max_memory_gbfloat | NoneExplicit memory budget in GB. None (default) measures available system RAM with headroom via device_memory_budget.None
min_jobsintMinimum number of workers (default: 1).1

Returns:

NameTypeDescription
intintWorker count for joblib.Parallel(n_jobs=...).

auto_select_backend

auto_select_backend(n_samples: int, n_features: int, cv: int = 1) -> Backend

Automatically select backend based on problem size.

Uses heuristics to decide between NumPy (CPU) and PyTorch (GPU) based on the computational workload. Small problems use NumPy to avoid GPU transfer overhead. Large problems prefer GPU when available.

Parameters:

NameTypeDescriptionDefault
n_samplesintNumber of samples in datasetrequired
n_featuresintNumber of features in datasetrequired
cvint, default=1Number of cross-validation folds (multiplies effective size)1

Returns:

NameTypeDescription
BackendBackendSelected backend instance
Notes

Selection criteria:

  • Small problems (< 10M elements): Use NumPy

  • Large problems (> 30M elements): Use GPU if available

  • Cross-validation: Prefer GPU even for medium problems

check_gpu_available

check_gpu_available() -> tuple[bool, dict[str, Any]]

Check if GPU acceleration is available.

Returns:

NameTypeDescription
tupletuple [ bool , dict [ str , Any ]](available, info) where: - available (bool): True if GPU (CUDA or MPS) is available - info (dict): Dictionary with keys: - ‘backend’: ‘torch’ or ‘numpy’ - ‘device’: ‘cpu’, ‘cuda’, or ‘mps’ - ‘device_name’: Human-readable device name

compute_oom_safe

compute_oom_safe(fn, *arrays, min_chunk: int = 1)

Run fn(*arrays) with reactive out-of-memory recovery.

All arrays must share their axis-0 length, and fn must map them to a numpy array whose axis 0 corresponds row-for-row to its inputs. On a device OOM the cache is emptied, the arrays are split in half along axis 0, and the halves are retried recursively; partial results are concatenated along axis 0.

Because splitting reuses the already generated inputs rather than re-drawing them, recovery never changes which permutations a seeded result is computed from — RNG-consuming input generation stays outside this function. For a row-independent fn the recovered output matches the unsplit computation to within floating-point reduction order (backends may block reductions differently per batch shape; observed differences are ~1 float32 ulp).

Parameters:

NameTypeDescriptionDefault
fnCallable mapping the arrays to a numpy result (axis-0 aligned).required
*arraysInput arrays sharing axis-0 length.()
min_chunkintChunk size below which an OOM is considered fatal.1

Returns:

TypeDescription
np.ndarray: fn’s result, possibly assembled from retried chunks.

device_memory_budget

device_memory_budget(backend: Backend | None = None, max_gpu_memory_gb: float | None = None, *, cap_for_batching: bool = False) -> float

Usable memory budget in GB for a backend’s device.

An explicit max_gpu_memory_gb always wins, uncapped. Otherwise the budget is measured at call time: free CUDA memory (with headroom) on CUDA devices; available system RAM (with headroom) for CPU and MPS, which share unified/system memory. When nothing can be measured the conservative 4 GB fallback applies.

Parameters:

NameTypeDescriptionDefault
backendBackend | NoneResolved Backend whose device the work runs on. None is treated as CPU.None
max_gpu_memory_gbfloat | NoneExplicit budget override in GB. Must be positive.None
cap_for_batchingboolPass True when the budget sizes batches — a measured budget is then capped at BATCH_WORKING_SET_CEILING_GB, because working sets beyond the saturation ceiling add allocation cost without throughput gain and starve unified-memory hosts. Never applied to an explicit max_gpu_memory_gb; capacity queries (the default) stay uncapped.False

Returns:

NameTypeDescription
floatfloatBudget in GB.

empty_device_cache

empty_device_cache() -> None

Release cached device memory. No-op without torch or a GPU.

gb_to_bytes

gb_to_bytes(gb: float) -> int

Convert a GB budget to bytes — the package’s one GB↔bytes conversion.

is_oom_error

is_oom_error(exc: BaseException) -> bool

True if exc is a device out-of-memory error (CUDA or MPS).

resolve_backend

resolve_backend(parallel)

Coerce a backend specifier into a Backend instance.

Accepts the values callers typically thread through the algorithms package (None/"cpu" → numpy, "gpu"/"torch" → torch, "numpy"/"auto" → their direct Backend constructors). Existing Backend instances are returned unchanged — this is the main reason to prefer resolve_backend over constructing a new Backend(...) at each call site: it avoids repeated device detection/torch imports when a backend has already been chosen upstream.

Parameters:

NameTypeDescriptionDefault
parallelBackend specifier. One of:
- None or "cpu": numpy backend. - "numpy", "torch", "auto": forwarded to Backend(...). - "gpu": alias for "torch" (auto-detects cuda/mps/cpu). - An existing Backend instance (returned as-is).
required

Returns:

NameTypeDescription
BackendResolved backend instance.