Skip to content

Commit

Permalink
Leverage dpnp.cumsum through dpctl.tensor implementation (IntelPyth…
Browse files Browse the repository at this point in the history
…on#1772)

* Implement dpnp.cumsum through dpctl.tensor

* Aligned dpnp.ndarray docs

* Fixed tests for cumprod on Windows

* Enabled missing test_sum_axis2_float16 test

* Added tests

* Align return logic with dpnp.sum()

* Used a helper function to assert arrays for tests of SYCL queue

* Mute a test for dpnp.cumprod on Windows until proper impl is done
  • Loading branch information
antonwolfy authored Apr 9, 2024
1 parent 2a2cdfa commit 9705a51
Show file tree
Hide file tree
Showing 10 changed files with 606 additions and 107 deletions.
1 change: 0 additions & 1 deletion dpnp/dpnp_algo/dpnp_algo_mathematical.pxi
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ and the rest of the library

__all__ += [
"dpnp_cumprod",
"dpnp_cumsum",
"dpnp_ediff1d",
"dpnp_fabs",
"dpnp_fmod",
Expand Down
42 changes: 21 additions & 21 deletions dpnp/dpnp_array.py
Original file line number Diff line number Diff line change
Expand Up @@ -533,7 +533,7 @@ def astype(self, dtype, order="K", casting="unsafe", subok=True, copy=True):
"""
Copy the array with data type casting.
For full documentation refer to :obj:`numpy.ndarray.astype`.
Refer to :obj:`dpnp.astype` for full documentation.
Parameters
----------
Expand Down Expand Up @@ -593,7 +593,12 @@ def astype(self, dtype, order="K", casting="unsafe", subok=True, copy=True):
# 'byteswap',

def choose(input, choices, out=None, mode="raise"):
"""Construct an array from an index array and a set of arrays to choose from."""
"""
Construct an array from an index array and a set of arrays to choose from.
Refer to :obj:`dpnp.choose` for full documentation.
"""

return dpnp.choose(input, choices, out, mode)

Expand All @@ -613,7 +618,7 @@ def conj(self):
"""
Complex-conjugate all elements.
For full documentation refer to :obj:`numpy.ndarray.conj`.
Refer to :obj:`dpnp.conjugate` for full documentation.
"""

Expand All @@ -626,7 +631,7 @@ def conjugate(self):
"""
Return the complex conjugate, element-wise.
For full documentation refer to :obj:`numpy.ndarray.conjugate`.
Refer to :obj:`dpnp.conjugate` for full documentation.
"""

Expand Down Expand Up @@ -683,9 +688,7 @@ def cumsum(self, axis=None, dtype=None, out=None):
"""
Return the cumulative sum of the elements along the given axis.
See Also
--------
:obj:`dpnp.cumsum`
Refer to :obj:`dpnp.cumsum` for full documentation.
"""

Expand All @@ -697,9 +700,7 @@ def diagonal(input, offset=0, axis1=0, axis2=1):
"""
Return specified diagonals.
See Also
--------
:obj:`dpnp.diagonal`
Refer to :obj:`dpnp.diagonal` for full documentation.
"""

Expand All @@ -709,7 +710,7 @@ def dot(self, b, out=None):
"""
Dot product of two arrays.
For full documentation refer to :obj:`dpnp.dot`.
Refer to :obj:`dpnp.dot` for full documentation.
Examples
--------
Expand Down Expand Up @@ -1013,7 +1014,7 @@ def prod(
"""
Returns the prod along a given axis.
For full documentation refer to :obj:`dpnp.prod`.
Refer to :obj:`dpnp.prod` for full documentation.
"""

Expand All @@ -1023,7 +1024,7 @@ def put(self, indices, vals, /, *, axis=None, mode="wrap"):
"""
Puts values of an array into another array along a given axis.
For full documentation refer to :obj:`numpy.put`.
Refer to :obj:`dpnp.put` for full documentation.
"""

Expand All @@ -1033,7 +1034,7 @@ def ravel(self, order="C"):
"""
Return a contiguous flattened array.
For full documentation refer to :obj:`dpnp.ravel`.
Refer to :obj:`dpnp.ravel` for full documentation.
"""

Expand Down Expand Up @@ -1083,7 +1084,7 @@ def repeat(self, repeats, axis=None):
"""
Repeat elements of an array.
For full documentation refer to :obj:`dpnp.repeat`.
Refer to :obj:`dpnp.repeat` for full documentation.
"""

Expand All @@ -1093,7 +1094,7 @@ def reshape(self, *sh, **kwargs):
"""
Returns an array containing the same data with a new shape.
For full documentation refer to :obj:`numpy.ndarray.reshape`.
Refer to :obj:`dpnp.reshape` for full documentation.
Returns
-------
Expand Down Expand Up @@ -1124,8 +1125,7 @@ def round(self, decimals=0, out=None):
"""
Return array with each element rounded to the given number of decimals.
.. seealso::
:obj:`dpnp.around` for full documentation.
Refer to :obj:`dpnp.round` for full documentation.
"""

Expand Down Expand Up @@ -1271,7 +1271,7 @@ def sum(
"""
Returns the sum along a given axis.
For full documentation refer to :obj:`dpnp.sum`.
Refer to :obj:`dpnp.sum` for full documentation.
"""

Expand All @@ -1289,7 +1289,7 @@ def swapaxes(self, axis1, axis2):
"""
Interchange two axes of an array.
For full documentation refer to :obj:`numpy.swapaxes`.
Refer to :obj:`dpnp.swapaxes` for full documentation.
"""

Expand All @@ -1299,7 +1299,7 @@ def take(self, indices, /, *, axis=None, out=None, mode="wrap"):
"""
Take elements from an array along an axis.
For full documentation refer to :obj:`numpy.take`.
Refer to :obj:`dpnp.take` for full documentation.
"""

Expand Down
98 changes: 78 additions & 20 deletions dpnp/dpnp_iface_mathematical.py
Original file line number Diff line number Diff line change
Expand Up @@ -855,42 +855,100 @@ def cumprod(x1, **kwargs):
return call_origin(numpy.cumprod, x1, **kwargs)


def cumsum(x1, **kwargs):
def cumsum(a, axis=None, dtype=None, out=None):
"""
Return the cumulative sum of the elements along a given axis.
For full documentation refer to :obj:`numpy.cumsum`.
Limitations
-----------
Parameter `x` is supported as :obj:`dpnp.ndarray`.
Keyword argument `kwargs` is currently unsupported.
Otherwise the function will be executed sequentially on CPU.
Input array data types are limited by supported DPNP :ref:`Data types`.
Parameters
----------
a : {dpnp.ndarray, usm_ndarray}
Input array.
axis : int, optional
Axis along which the cumulative sum is computed. The default (``None``)
is to compute the cumsum over the flattened array.
dtype : dtype, optional
Type of the returned array and of the accumulator in which the elements
are summed. If `dtype` is not specified, it defaults to the dtype of
`a`, unless `a` has an integer dtype with a precision less than that of
the default platform integer. In that case, the default platform
integer is used.
out : {dpnp.ndarray, usm_ndarray}, optional
Alternative output array in which to place the result. It must have the
same shape and buffer length as the expected output but the type will
be cast if necessary.
Returns
-------
out : dpnp.ndarray
A new array holding the result is returned unless `out` is specified as
:class:`dpnp.ndarray`, in which case a reference to `out` is returned.
The result has the same size as `a`, and the same shape as `a` if `axis`
is not ``None`` or `a` is a 1-d array.
See Also
--------
:obj:`dpnp.diff` : Calculate the n-th discrete difference along the given axis.
:obj:`dpnp.sum` : Sum array elements.
:obj:`dpnp.diff` : Calculate the n-th discrete difference along given axis.
Examples
--------
>>> import dpnp as np
>>> a = np.array([1, 2, 4])
>>> result = np.cumsum(a)
>>> [x for x in result]
[1, 2, 7]
>>> b = np.array([[1, 2, 3], [4, 5, 6]])
>>> result = np.cumsum(b)
>>> [x for x in result]
[1, 2, 6, 10, 15, 21]
>>> a = np.array([[1, 2, 3], [4, 5, 6]])
>>> a
array([[1, 2, 3],
[4, 5, 6]])
>>> np.cumsum(a)
array([ 1, 3, 6, 10, 15, 21])
>>> np.cumsum(a, dtype=float) # specifies type of output value(s)
array([ 1., 3., 6., 10., 15., 21.])
>>> np.cumsum(a, axis=0) # sum over rows for each of the 3 columns
array([[1, 2, 3],
[5, 7, 9]])
>>> np.cumsum(a, axis=1) # sum over columns for each of the 2 rows
array([[ 1, 3, 6],
[ 4, 9, 15]])
``cumsum(b)[-1]`` may not be equal to ``sum(b)``
>>> b = np.array([1, 2e-9, 3e-9] * 10000)
>>> b.cumsum().dtype == b.sum().dtype == np.float64
True
>>> b.cumsum()[-1] == b.sum()
array(False)
"""

x1_desc = dpnp.get_dpnp_descriptor(x1, copy_when_nondefault_queue=False)
if x1_desc and not kwargs:
return dpnp_cumsum(x1_desc).get_pyobj()
dpnp.check_supported_arrays_type(a)
if a.ndim > 1 and axis is None:
usm_a = dpnp.ravel(a).get_array()
else:
usm_a = dpnp.get_usm_ndarray(a)

input_out = out
if out is None:
usm_out = None
else:
dpnp.check_supported_arrays_type(out)

# get dtype used by dpctl for result array in cumulative_sum
if dtype is None:
res_dt = dtu._default_accumulation_dtype(a.dtype, a.sycl_queue)
else:
res_dt = dpnp.dtype(dtype)
res_dt = dtu._to_device_supported_dtype(res_dt, a.sycl_device)

# dpctl requires strict data type matching of out array with the result
if out.dtype != res_dt:
out = dpnp.astype(out, dtype=res_dt, copy=False)

usm_out = dpnp.get_usm_ndarray(out)

return call_origin(numpy.cumsum, x1, **kwargs)
res_usm = dpt.cumulative_sum(usm_a, axis=axis, dtype=dtype, out=usm_out)
res = dpnp_array._create_from_usm_ndarray(res_usm)
return dpnp.get_result_array(res, input_out, casting="unsafe")


def diff(a, n=1, axis=-1, prepend=None, append=None):
Expand Down
7 changes: 5 additions & 2 deletions tests/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@ def assert_dtype_allclose(
"""

list_64bit_types = [numpy.float64, numpy.complex128]
is_inexact = lambda x: dpnp.issubdtype(x.dtype, dpnp.inexact)
is_inexact = lambda x: hasattr(x, "dtype") and dpnp.issubdtype(
x.dtype, dpnp.inexact
)

if is_inexact(dpnp_arr) or is_inexact(numpy_arr):
tol_dpnp = (
dpnp.finfo(dpnp_arr).resolution
Expand Down Expand Up @@ -73,7 +76,7 @@ def assert_dtype_allclose(
assert dpnp_arr_dtype.kind == numpy_arr_dtype.kind
else:
assert_array_equal(dpnp_arr.asnumpy(), numpy_arr)
if check_type:
if check_type and hasattr(numpy_arr, "dtype"):
if check_only_type_kind:
assert dpnp_arr.dtype.kind == numpy_arr.dtype.kind
else:
Expand Down
15 changes: 0 additions & 15 deletions tests/skipped_tests.tbl
Original file line number Diff line number Diff line change
Expand Up @@ -479,21 +479,6 @@ tests/third_party/cupy/math_tests/test_misc.py::TestConvolve::test_convolve_diff

tests/third_party/cupy/math_tests/test_rounding.py::TestRounding::test_fix

tests/third_party/cupy/math_tests/test_sumprod.py::TestCumprod::test_ndarray_cumprod_2dim_with_axis
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumprod::test_cumprod_arraylike
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumprod::test_cumprod_huge_array
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumprod::test_cumprod_numpy_array
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumprod::test_cumprod_out_noncontiguous
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumprod::test_cumprod_1dim
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumprod::test_cumprod_2dim_without_axis

tests/third_party/cupy/math_tests/test_sumprod.py::TestCumsum::test_cumsum_arraylike[_param_0_{axis=0}]
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumsum::test_cumsum_arraylike[_param_1_{axis=1}]
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumsum::test_cumsum_arraylike[_param_2_{axis=2}]
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumsum::test_cumsum_numpy_array[_param_0_{axis=0}]
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumsum::test_cumsum_numpy_array[_param_1_{axis=1}]
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumsum::test_cumsum_numpy_array[_param_2_{axis=2}]

tests/third_party/cupy/math_tests/test_trigonometric.py::TestUnwrap::test_unwrap_1dim
tests/third_party/cupy/math_tests/test_trigonometric.py::TestUnwrap::test_unwrap_1dim_with_discont
tests/third_party/cupy/math_tests/test_trigonometric.py::TestUnwrap::test_unwrap_1dim_with_period
Expand Down
22 changes: 0 additions & 22 deletions tests/skipped_tests_gpu.tbl
Original file line number Diff line number Diff line change
Expand Up @@ -586,28 +586,6 @@ tests/third_party/cupy/math_tests/test_misc.py::TestConvolve::test_convolve_diff

tests/third_party/cupy/math_tests/test_rounding.py::TestRounding::test_fix

tests/third_party/cupy/math_tests/test_sumprod.py::TestCumprod::test_ndarray_cumprod_2dim_with_axis
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumprod::test_cumprod_arraylike
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumprod::test_cumprod_huge_array
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumprod::test_cumprod_numpy_array
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumprod::test_cumprod_out_noncontiguous
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumprod::test_cumprod_1dim
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumprod::test_cumprod_2dim_without_axis

tests/third_party/cupy/math_tests/test_sumprod.py::TestCumsum::test_cumsum[_param_0_{axis=0}]
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumsum::test_cumsum[_param_1_{axis=1}]
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumsum::test_cumsum[_param_2_{axis=2}]
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumsum::test_cumsum_2dim[_param_0_{axis=0}]
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumsum::test_cumsum_2dim[_param_1_{axis=1}]
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumsum::test_cumsum_2dim[_param_2_{axis=2}]

tests/third_party/cupy/math_tests/test_sumprod.py::TestCumsum::test_cumsum_arraylike[_param_0_{axis=0}]
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumsum::test_cumsum_arraylike[_param_1_{axis=1}]
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumsum::test_cumsum_arraylike[_param_2_{axis=2}]
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumsum::test_cumsum_numpy_array[_param_0_{axis=0}]
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumsum::test_cumsum_numpy_array[_param_1_{axis=1}]
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumsum::test_cumsum_numpy_array[_param_2_{axis=2}]

tests/third_party/cupy/math_tests/test_trigonometric.py::TestUnwrap::test_unwrap_1dim
tests/third_party/cupy/math_tests/test_trigonometric.py::TestUnwrap::test_unwrap_1dim_with_discont
tests/third_party/cupy/math_tests/test_trigonometric.py::TestUnwrap::test_unwrap_1dim_with_period
Expand Down
Loading

0 comments on commit 9705a51

Please sign in to comment.