9. Backend¶
The eminus code is written such that multiple array backends can be used. Naturally, this adds a layer of complexity. Luckily, not too much. This document will inform developers about possible intricacies.
9.1. Writing backend agnostic code¶
Writing backend agnostic code is most of the time straightforward. Where one normally uses NumPy, e.g., with
import numpy as np
np.ones(3)
one can now write
from eminus import backend as xp
xp.ones(3)
One caveat is that one has to type imports of submodules explicitly instead of relying on from
imports.
from eminus import backend as xp
xp.linalg.det([[3]])
This is because the backend module will be determined at runtime.
from
imports do not support this dynamic system.
The backend can be changed using the config
module with
import eminus
eminus.backend = "numpy"
Currently supported backends are NumPy and Torch.
There are a few differences between the two backends.
Luckily, many can be mitigated using the array-api-compat package.
In cases where this does not work, a wrapper function can be added to the backend module, e.g., to get xp.delete
to work for Torch tensors.
The largest difference can be found in the strictness of types. Where NumPy easily casts types, e.g., in a matrix multiplication between a float and a complex type, Torch needs an additional cast from float to complex.
To simplify some operations, there are also helper functions available in the backend
module, e.g., to check if a variable is a backend array
from eminus import backend as xp
a = xp.ones(3)
xp.is_array(a)
9.1.1. GPU¶
Torch supports calculations on the GPU, while NumPy does not.
However, some functionalities are exclusive to NumPy (mostly in the extras
).
Therefore, it is sometimes needed to convert the Torch GPU tensors to NumPy CPU arrays.
For this, the to_np
helper function can be utilized
from eminus import backend as xp
from eminus import config
config.use_gpu = True
a = xp.ones(3)
a = xp.to_np(a)
9.1.2. Running tests¶
To test the functionality for a backend, one can select it by using the custom pytest --backend
option.
By default, the tests will be performed using NumPy.
The tests are written such that they work independently of the selected backend.
To test arrays that may exist on different devices or as arrays of different backends, one can use the utility functions in the testing
module.