Skip to content

Commit

Permalink
gh-218: add math ops binding & start vector impl for package
Browse files Browse the repository at this point in the history
  • Loading branch information
EgorOrachyov committed Aug 29, 2023
1 parent 911dcd3 commit d71489b
Show file tree
Hide file tree
Showing 14 changed files with 401 additions and 81 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@ add_library(spla SHARED
src/binding/c_algorithm.cpp
src/binding/c_array.cpp
src/binding/c_config.hpp
src/binding/c_exec.cpp
src/binding/c_library.cpp
src/binding/c_matrix.cpp
src/binding/c_memview.cpp
Expand Down
16 changes: 16 additions & 0 deletions include/spla.h
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,22 @@ SPLA_API spla_Status spla_Algorithm_tc(int* ntrins, spla_Matrix A, spla_Matrix B

//////////////////////////////////////////////////////////////////////////////////////

/* Scheduling and operations execution */

SPLA_API spla_Status spla_Exec_mxmT_masked(spla_Matrix R, spla_Matrix mask, spla_Matrix A, spla_Matrix B, spla_OpBinary op_multiply, spla_OpBinary op_add, spla_OpSelect op_select, spla_Scalar init, spla_Descriptor desc, spla_ScheduleTask* task);
SPLA_API spla_Status spla_Exec_mxv_masked(spla_Vector r, spla_Vector mask, spla_Matrix M, spla_Vector v, spla_OpBinary op_multiply, spla_OpBinary op_add, spla_OpSelect op_select, spla_Scalar init, spla_Descriptor desc, spla_ScheduleTask* task);
SPLA_API spla_Status spla_Exec_vxm_masked(spla_Vector r, spla_Vector mask, spla_Vector v, spla_Matrix M, spla_OpBinary op_multiply, spla_OpBinary op_add, spla_OpSelect op_select, spla_Scalar init, spla_Descriptor desc, spla_ScheduleTask* task);
SPLA_API spla_Status spla_Exec_m_reduce_by_row(spla_Vector r, spla_Matrix M, spla_OpBinary op_reduce, spla_Scalar init, spla_Descriptor desc, spla_ScheduleTask* task);
SPLA_API spla_Status spla_Exec_m_reduce(spla_Scalar r, spla_Scalar s, spla_Matrix M, spla_OpBinary op_reduce, spla_Descriptor desc, spla_ScheduleTask* task);
SPLA_API spla_Status spla_Exec_v_eadd(spla_Vector r, spla_Vector u, spla_Vector v, spla_OpBinary op, spla_Descriptor desc, spla_ScheduleTask* task);
SPLA_API spla_Status spla_Exec_v_eadd_fdb(spla_Vector r, spla_Vector v, spla_Vector fdb, spla_OpBinary op, spla_Descriptor desc, spla_ScheduleTask* task);
SPLA_API spla_Status spla_Exec_v_assign_masked(spla_Vector r, spla_Vector mask, spla_Scalar value, spla_OpBinary op_assign, spla_OpSelect op_select, spla_Descriptor desc, spla_ScheduleTask* task);
SPLA_API spla_Status spla_Exec_v_map(spla_Vector r, spla_Vector v, spla_OpUnary op, spla_Descriptor desc, spla_ScheduleTask* task);
SPLA_API spla_Status spla_Exec_v_reduce(spla_Scalar r, spla_Scalar s, spla_Vector v, spla_OpBinary op_reduce, spla_Descriptor desc, spla_ScheduleTask* task);
SPLA_API spla_Status spla_Exec_v_count_mf(spla_Scalar r, spla_Vector v, spla_Descriptor desc, spla_ScheduleTask* task);

//////////////////////////////////////////////////////////////////////////////////////

#if defined(__cplusplus)
}
#endif
Expand Down
3 changes: 3 additions & 0 deletions python/example.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@

s = pyspla.Scalar(value=10, dtype=pyspla.INT)
print(s)

v = pyspla.Vector.from_lists([1, 2, 3], [-10, 100, 20], shape=10, dtype=pyspla.INT)
print(v.reduce(pyspla.INT.PLUS))
2 changes: 2 additions & 0 deletions python/pyspla/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@
bridge.initialize()

from .library import *
from .descriptor import *
from .op import *
from .object import *
from .schedule import *
Expand All @@ -190,6 +191,7 @@
"INT",
"UINT",
"FLOAT",
"Descriptor",
"Op",
"OpUnary",
"OpBinary",
Expand Down
15 changes: 4 additions & 11 deletions python/pyspla/array.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,12 @@ class Array(Object):
Notes
-----
Array provides features for:
- fill with values
- read-back by value
- source for vector construction
- source for matrix construction
Array typical usage:
- (1) Instantiate array primitive
- (2) Fill with values from your data
- (3) Use array to build entire vector or matrix
- (4) Read-back results of computations from vector or matrix
- Instantiate array primitive
- Fill with values from your data
- Use array to build entire vector or matrix
- Read-back results of computations from vector or matrix
Details
-------
Expand Down
41 changes: 38 additions & 3 deletions python/pyspla/bridge.py
Original file line number Diff line number Diff line change
Expand Up @@ -296,9 +296,9 @@ def load_library(lib_path):
_spla.spla_MemView_make.restype = _status_t
_spla.spla_MemView_read.restype = _status_t
_spla.spla_MemView_write.restype = _status_t
_spla.spla_MemView_get_buffer = _status_t
_spla.spla_MemView_get_size = _status_t
_spla.spla_MemView_is_mutable = _status_t
_spla.spla_MemView_get_buffer.restype = _status_t
_spla.spla_MemView_get_size.restype = _status_t
_spla.spla_MemView_is_mutable.restype = _status_t

_spla.spla_MemView_make.argtypes = [_p_object_t, ctypes.c_void_p, ctypes.c_size_t, ctypes.c_int]
_spla.spla_MemView_read.argtypes = [_object_t, ctypes.c_size_t, ctypes.c_size_t, ctypes.c_void_p]
Expand Down Expand Up @@ -411,6 +411,41 @@ def load_library(lib_path):
_spla.spla_Algorithm_pr.argtypes = [_p_object_t, _object_t, _float, _float, _object_t]
_spla.spla_Algorithm_tc.argtypes = [_p_int, _object_t, _object_t, _object_t]

_spla.spla_Exec_mxmT_masked.restype = _status_t
_spla.spla_Exec_mxv_masked.restype = _status_t
_spla.spla_Exec_vxm_masked.restype = _status_t
_spla.spla_Exec_m_reduce_by_row.restype = _status_t
_spla.spla_Exec_m_reduce.restype = _status_t
_spla.spla_Exec_v_eadd.restype = _status_t
_spla.spla_Exec_v_eadd_fdb.restype = _status_t
_spla.spla_Exec_v_assign_masked.restype = _status_t
_spla.spla_Exec_v_map.restype = _status_t
_spla.spla_Exec_v_reduce.restype = _status_t
_spla.spla_Exec_v_count_mf.restype = _status_t

_spla.spla_Exec_mxmT_masked.argtypes = \
[_object_t, _object_t, _object_t, _object_t, _object_t, _object_t, _object_t, _object_t, _object_t, _p_object_t]
_spla.spla_Exec_mxv_masked.argtypes = \
[_object_t, _object_t, _object_t, _object_t, _object_t, _object_t, _object_t, _object_t, _object_t, _p_object_t]
_spla.spla_Exec_vxm_masked.argtypes = \
[_object_t, _object_t, _object_t, _object_t, _object_t, _object_t, _object_t, _object_t, _object_t, _p_object_t]
_spla.spla_Exec_m_reduce_by_row.argtypes = \
[_object_t, _object_t, _object_t, _object_t, _object_t, _p_object_t]
_spla.spla_Exec_m_reduce.argtypes = \
[_object_t, _object_t, _object_t, _object_t, _object_t, _p_object_t]
_spla.spla_Exec_v_eadd.argtypes = \
[_object_t, _object_t, _object_t, _object_t, _object_t, _p_object_t]
_spla.spla_Exec_v_eadd_fdb.argtypes = \
[_object_t, _object_t, _object_t, _object_t, _object_t, _p_object_t]
_spla.spla_Exec_v_assign_masked.argtypes = \
[_object_t, _object_t, _object_t, _object_t, _object_t, _object_t, _p_object_t]
_spla.spla_Exec_v_map.argtypes = \
[_object_t, _object_t, _object_t, _object_t, _p_object_t]
_spla.spla_Exec_v_reduce.argtypes = \
[_object_t, _object_t, _object_t, _object_t, _object_t, _p_object_t]
_spla.spla_Exec_v_count_mf.argtypes = \
[_object_t, _object_t, _object_t, _p_object_t]


def default_callback(status, msg, file, function, line, user_data):
decoded_msg = msg.decode("utf-8")
Expand Down
51 changes: 51 additions & 0 deletions python/pyspla/descriptor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"""
Wrapped native (spla C API) descriptor object implementation.
"""

__copyright__ = "Copyright (c) 2021-2023 SparseLinearAlgebra"

__license__ = """
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""

import ctypes

from .bridge import backend, check
from .object import Object


class Descriptor(Object):
"""
Wrapper for a descriptor object from a library.
"""

def __init__(self, label=None, hnd=None):
"""
Creates a new descriptor from existing hnd or making new for a buffer resource.
:param label: optional: str. default: None.
MemView name for debugging.
:param hnd: optional: ctypes.c_void_p. default: None.
MemView native void* handle to a C counterpart.
"""

super().__init__(label, hnd)
33 changes: 4 additions & 29 deletions python/pyspla/matrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,37 +36,12 @@ class Matrix:
Notes
-----
Matrix provides features for:
- incremental creation
- build from values
- read-back by value
- (tbd) transposition
- (tbd) triangular lower
- (tbd) triangular upper
- (tbd) element-wise addition
- (tbd) element-wise subtraction
- matrix-vector product
- (tbd) matrix-matrix product
- (tbd) matrix-matrix kronecker product
Matrix supports storage schemas:
- cpu lil (list of lists, for incremental build)
- cpu dok (dictionary of keys, for incremental build and per-value reed back)
- cpu coo (coordinate matrix format)
- cpu csr (compressed sparse rows)
- cpu csc (compressed sparse columns)
- acc coo (opencl)
- acc csr (opencl)
- acc csc (opencl)
Matrix typical usage:
- (1) Instantiate matrix primitive
- (2) Build incrementally from yours data source
- (3) Matrix usage in a sequence of math operations
- (4) Read-back matrix data to python to analyse results
- Instantiate matrix primitive
- Build incrementally from yours data source
- Matrix usage in a sequence of math operations
- Read-back matrix data to python to analyse results
Steps (2) and (4) requires internal format transformations and possible transfer of data
from acc (GPU) side if acceleration was employed in computations. These steps may be very
Expand Down
8 changes: 4 additions & 4 deletions python/pyspla/op.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def __init__(self, hnd, name, dtype_res, label=None):
assert name
assert dtype_res

super().__init__(hnd, label)
super().__init__(label, hnd)

self._name = name
self._dtype_res = dtype_res
Expand Down Expand Up @@ -124,7 +124,7 @@ def __init__(self, hnd, name, dtype_res, dtype_arg0, label=None):
Optional debug label to set for the object.
"""

super().__init__(hnd, name, dtype_res, label)
super().__init__(hnd=hnd, name=name, dtype_res=dtype_res, label=label)

self._dtype_arg0 = dtype_arg0

Expand Down Expand Up @@ -172,7 +172,7 @@ def __init__(self, hnd, name, dtype_res, dtype_arg0, dtype_arg1, label=None):
Optional debug label to set for the object.
"""

super().__init__(hnd, name, dtype_res, label)
super().__init__(hnd=hnd, name=name, dtype_res=dtype_res, label=label)

self._dtype_arg0 = dtype_arg0
self._dtype_arg1 = dtype_arg1
Expand Down Expand Up @@ -224,7 +224,7 @@ def __init__(self, hnd, name, dtype_arg0, label=None):

from .type import BOOL

super().__init__(hnd, name, BOOL, label)
super().__init__(hnd=hnd, name=name, dtype_res=BOOL, label=label)

self._dtype_arg0 = dtype_arg0

Expand Down
17 changes: 5 additions & 12 deletions python/pyspla/scalar.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,12 @@ class Scalar(Object):
Notes
-----
Scalar provides features for:
- pack native value
- unpack native value
- pass value as a param to some operation
- get scalar as an operation result
Scalar typical usage:
- (1) Create scalar from python value
- (2) Pass scalar as argument to matrix/vector operation
- (3) Get scalar as a return value of some operation
- (4) Unpack value on python side
- Create scalar from python value
- Pass scalar as argument to matrix/vector operation
- Get scalar as a return value of some operation
- Unpack value on python side
Avoid intensive creation of scalar values. Prefer python native types.
Use scalars only if you want to parametrise matrix/vector operations.
Expand Down Expand Up @@ -129,7 +122,7 @@ def set(self, value=None):
Optional value to store in scalar.
"""

check(self._dtype._scalar_set(self._hnd, self._dtype._c_type(value)))
check(self._dtype._scalar_set(self._hnd, self._dtype._c_type(value if value else 0)))

def get(self):
"""
Expand Down
Loading

0 comments on commit d71489b

Please sign in to comment.