pyepri.backends
This module defines a standardized Backend class for unified use of numpy, cupy and torch libraries (see <class ‘backends.Backend’>).
This module also provides constructors of ready-to-use backends, see
create_numpy_backend()
: numpy backend constructor (CPU only)create_cupy_backend()
: cupy backend constructor (GPU only)create_torch_backend()
: torch backend constructor (CPU or GPU)
A backends.Backend
instance provides attributes for data type
mapping (the standardized type is a str, e.g., 'float32'
,
'float64'
, 'int32'
, …, is mapped to the library dependent
corresponding data types).
A Backend
instance also provides lambda function attributes
that are mapped to several standard lib-dependent functions
(lib.zeros
, lib.arange
, lib.sin
, lib.cos
,
lib.meshgrid
, …, for lib in {numpy
, cupy
, torch
})
but with unified fashion (parameters naming, default settings, etc).
For more details about how backend system works, you may consult the
Backend
class documentation by typing:
>>> import pyepri.backends as backends
>>> help(backends.Backend)
Examples of backend instantiation and utilization are also described in the constructor documentations:
>>> import pyepri.backends as backends
>>> help(backends.create_numpy_backend) # numpy backend constructor
>>> help(backends.create_cupy_backend) # cupy backend constructor
>>> help(backends.create_torch_backend) # torch backend constructor
Classes
Class for mapping our standardized data types and methods to the specified library (numpy, torch, cupy). |
Functions
Create a numpy backend. |
|
Create a cupy backend. |
|
|
Create a torch backend with specified device. |
Module Contents
- pyepri.backends.create_numpy_backend()[source]
Create a numpy backend.
- Returns:
backend – Backend configured to perform operations using numpy library on CPU device.
- Return type:
<class ‘backends.Backend’>
See also
backends.create_cupy_backend
,backends.create_torch_backend
Examples
The following example illustrate how one can call the
numpy.zeros
andnumpy.arange
functions from a backend output of thiscreate_numpy_backend()
function.>>> import pyepri.backends as backends >>> b = backends.create_numpy_backend() >>> x = b.zeros((10,),dtype='float64') >>> print(x) [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.] >>> print(type(x)) <class 'numpy.ndarray'> >>> print(x.dtype) float64 >>> y = b.arange(3,10,2,dtype='int32') # another example >>> print(y) [3 5 7 9] >>> z = b.arange(10) # b.arange behaves as its numpy counterpart >>> # (`start` and `end` parameters are optional >>> # as for numpy.arange) >>> print(z) [0 1 2 3 4 5 6 7 8 9]
- pyepri.backends.create_cupy_backend()[source]
Create a cupy backend.
- Returns:
backend – Backend configured to perform operations using cupy library on GPU device.
- Return type:
<class ‘backends.Backend’>
See also
backends.create_numpy_backend
,backends.create_torch_backend
Examples
The following example illustrate how one can call the cupy.zeros and cupy.arange functions from a backend output of this backends.create_cupy_backend function.
>>> import pyepri.backends as backends >>> b = backends.create_cupy_backend() >>> x = b.zeros((10,),dtype='float64') >>> print(x) [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.] >>> print(type(x)) <class 'cupy.ndarray'> >>> print(x.dtype) float64 >>> print(x.device) # should return a GPU device (e.g., >>> # <CUDA Device 0>) <CUDA Device 0> >>> y = b.arange(3,10,2,dtype='int32') # another example >>> print(y) [3 5 7 9] >>> z = b.arange(10) # b.arange behaves as its cuppy counterpart >>> # (`start` and `end` parameters are optional >>> # as for cupy.arange) >>> print(z) [0 1 2 3 4 5 6 7 8 9]
- pyepri.backends.create_torch_backend(device)[source]
Create a torch backend with specified device.
Parameter
- devicestr
One of {‘cpu’, ‘cuda’, ‘cuda:X’} with X = device index.
- returns:
backend – A backends.Backend instance configured to perform operations using torch library on the specified device.
- rtype:
<class ‘backends.Backend’>
Notes
This function will raise an error if torch library is not installed or if the input device argument is not available on your system.
See also
backends.create_numpy_backend
,backends.create_cupy_backend
Examples
The following example illustrate how one can call the
torch.zeros
andtorch.arange
functions from a backend output of thiscreate_torch_backend()
function.Example 1: create and use a torch backend on ‘cpu’ device
To run the following example torch library should be installed on your system (otherwise the second line of this example will raise an error).
>>> import pyepri.backends as backends >>> b = backends.create_torch_backend('cpu') >>> x = b.zeros((10,),dtype='float64') # type is specified using a >>> # str (here 'float64') >>> print(x) tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], dtype=torch.float64) >>> print(x.device) # device is 'cpu' because 'cpu' was used as >>> # input in line 2 of this example cpu >>> y = b.arange(3,10,2,dtype='int32') # another example >>> print(y) tensor([3, 5, 7, 9], dtype=torch.int32) >>> print(y.device) cpu >>> z = b.arange(10) # b.arange behaves as its torch counterpart >>> # (`start` and `end` parameters are optional >>> # as for torch.arange) >>> print(z) tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
Example 2: create and use a torch backend on ‘cuda’ device
To run the following example torch library should be installed on your system and ‘cuda’ device should be available (otherwise the second line of this example will raise an error)
>>> import pyepri.backends as backends >>> b = backends.create_torch_backend('cuda') >>> x = b.zeros((10,),dtype='float64') # type is specified using a >>> # str (here 'float64') >>> print(x) # device is now cuda:0 (can be cuda:X with X = one >>> # available device index on your own system) tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], device='cuda:0', dtype=torch.float64) >>> y = b.arange(3,10,2,dtype='int32') # another example >>> print(y) tensor([3, 5, 7, 9], device='cuda:0', dtype=torch.int32) >>> z = b.arange(10) >>> print(z) tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], device='cuda:0')
- class pyepri.backends.Backend(lib, device)[source]
Class for mapping our standardized data types and methods to the specified library (numpy, torch, cupy).
Type correspondences
This package relies on data types specified with a str from which the library dependent data types will be inferred. The correspondence between the different data types is provided in the following Table.
str
lib = numpy or cupy
lib = torch
'int8'
lib.dtype('int8')
torch.int8
'int16'
lib.dtype('int16')
torch.int16
'int32'
lib.dtype('int32')
torch.int32
'int64'
lib.dtype('int64')
torch.int64
'float32'
lib.dtype('float32')
torch.float32
'float64'
lib.dtype('float64')
torch.float64
'complex64'
lib.dtype('complex64')
torch.complex64
'complex128'
lib.dtype('complex128')
torch.complex128
None
lib.dtype(None)
None
The mapping between the data types in str format and those of the targeted library can be done using the dtypes and invdtypes dictionary attributes described below.
We also provide a str to str mapping towards complex data types (non invertible mapping) :
data type
complex data type
'int8'
None
'int16'
None
'int32'
'complex64'
'float32'
'complex64'
'complex64'
'complex64'
'int64'
'complex128'
'float64'
'complex128'
'complex128'
'complex128'
The above mapping can be used to infer the data type of a complex array computed from another (non necessarily complex) input array (e.g., infer the data type of the discrete Fourier transform of an input array).
Contextual attributes
- lib<class ‘module’>
One of {numpy, cupy, torch}.
- devicestr
Device identifier (see constructor documentation below).
- cls<class ‘type’>
Native array data type in the backend library, as described below.
lib
cls
numpy
<class ‘numpy.ndarray’>
cupy
<class ‘cupy.ndarray’>
torch
<class ‘torch.Tensor’>
Data type mapping attributes
- str_to_lib_dtypesdict
Mapping data types in standardized str format -> lib dependent data types (see above).
- lib_to_str_dtypesdict
Invert of the str_to_lib_dtypes mapping (lib dependent data types -> data types in standardized str format).
- mapping_to_complex_dtypesdict
Mapping from data type in standardized str format -> complex data type in standardized str format (see above).
Other attributes (library-dependent methods)
An instance
backend
with classpyepri.backends.Backend
remaps library dependent methods to basically the same methods coming frombackend.lib
but with standardized usage (e.g.backend.meshgrid
can remap to{numpy or cupy or torch}.meshgrid
depending onbackend.lib
).A mini documentation is provided for each standardized method and can be displayed using the
help()
function, as illustrated below.>>> import pyepri.backends as backends >>> backend = backends.create_numpy_backend() >>> help(backend.meshgrid) ...Help on function <lambda> in module pyepri.backends: ... ...<lambda> lambda *xi, indexing='xy' ... return numpy.meshgrid(*xi, indexing=indexing)
- lib
- is_backend_compliant
- mapping_to_complex_dtypes
- lib_to_str_dtypes
- sqrt
- sin
- cos
- arccos
- arctan2
- real
- argwhere
- abs
- tile
- moveaxis
- meshgrid
- exp
- __doc__