Skip to content

Commit 9705a51

Browse files
authored
Leverage dpnp.cumsum through dpctl.tensor implementation (#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
1 parent 2a2cdfa commit 9705a51

10 files changed

Lines changed: 606 additions & 107 deletions

File tree

dpnp/dpnp_algo/dpnp_algo_mathematical.pxi

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ and the rest of the library
3737

3838
__all__ += [
3939
"dpnp_cumprod",
40-
"dpnp_cumsum",
4140
"dpnp_ediff1d",
4241
"dpnp_fabs",
4342
"dpnp_fmod",

dpnp/dpnp_array.py

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,7 @@ def astype(self, dtype, order="K", casting="unsafe", subok=True, copy=True):
533533
"""
534534
Copy the array with data type casting.
535535
536-
For full documentation refer to :obj:`numpy.ndarray.astype`.
536+
Refer to :obj:`dpnp.astype` for full documentation.
537537
538538
Parameters
539539
----------
@@ -593,7 +593,12 @@ def astype(self, dtype, order="K", casting="unsafe", subok=True, copy=True):
593593
# 'byteswap',
594594

595595
def choose(input, choices, out=None, mode="raise"):
596-
"""Construct an array from an index array and a set of arrays to choose from."""
596+
"""
597+
Construct an array from an index array and a set of arrays to choose from.
598+
599+
Refer to :obj:`dpnp.choose` for full documentation.
600+
601+
"""
597602

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

@@ -613,7 +618,7 @@ def conj(self):
613618
"""
614619
Complex-conjugate all elements.
615620
616-
For full documentation refer to :obj:`numpy.ndarray.conj`.
621+
Refer to :obj:`dpnp.conjugate` for full documentation.
617622
618623
"""
619624

@@ -626,7 +631,7 @@ def conjugate(self):
626631
"""
627632
Return the complex conjugate, element-wise.
628633
629-
For full documentation refer to :obj:`numpy.ndarray.conjugate`.
634+
Refer to :obj:`dpnp.conjugate` for full documentation.
630635
631636
"""
632637

@@ -683,9 +688,7 @@ def cumsum(self, axis=None, dtype=None, out=None):
683688
"""
684689
Return the cumulative sum of the elements along the given axis.
685690
686-
See Also
687-
--------
688-
:obj:`dpnp.cumsum`
691+
Refer to :obj:`dpnp.cumsum` for full documentation.
689692
690693
"""
691694

@@ -697,9 +700,7 @@ def diagonal(input, offset=0, axis1=0, axis2=1):
697700
"""
698701
Return specified diagonals.
699702
700-
See Also
701-
--------
702-
:obj:`dpnp.diagonal`
703+
Refer to :obj:`dpnp.diagonal` for full documentation.
703704
704705
"""
705706

@@ -709,7 +710,7 @@ def dot(self, b, out=None):
709710
"""
710711
Dot product of two arrays.
711712
712-
For full documentation refer to :obj:`dpnp.dot`.
713+
Refer to :obj:`dpnp.dot` for full documentation.
713714
714715
Examples
715716
--------
@@ -1013,7 +1014,7 @@ def prod(
10131014
"""
10141015
Returns the prod along a given axis.
10151016
1016-
For full documentation refer to :obj:`dpnp.prod`.
1017+
Refer to :obj:`dpnp.prod` for full documentation.
10171018
10181019
"""
10191020

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

@@ -1033,7 +1034,7 @@ def ravel(self, order="C"):
10331034
"""
10341035
Return a contiguous flattened array.
10351036
1036-
For full documentation refer to :obj:`dpnp.ravel`.
1037+
Refer to :obj:`dpnp.ravel` for full documentation.
10371038
10381039
"""
10391040

@@ -1083,7 +1084,7 @@ def repeat(self, repeats, axis=None):
10831084
"""
10841085
Repeat elements of an array.
10851086
1086-
For full documentation refer to :obj:`dpnp.repeat`.
1087+
Refer to :obj:`dpnp.repeat` for full documentation.
10871088
10881089
"""
10891090

@@ -1093,7 +1094,7 @@ def reshape(self, *sh, **kwargs):
10931094
"""
10941095
Returns an array containing the same data with a new shape.
10951096
1096-
For full documentation refer to :obj:`numpy.ndarray.reshape`.
1097+
Refer to :obj:`dpnp.reshape` for full documentation.
10971098
10981099
Returns
10991100
-------
@@ -1124,8 +1125,7 @@ def round(self, decimals=0, out=None):
11241125
"""
11251126
Return array with each element rounded to the given number of decimals.
11261127
1127-
.. seealso::
1128-
:obj:`dpnp.around` for full documentation.
1128+
Refer to :obj:`dpnp.round` for full documentation.
11291129
11301130
"""
11311131

@@ -1271,7 +1271,7 @@ def sum(
12711271
"""
12721272
Returns the sum along a given axis.
12731273
1274-
For full documentation refer to :obj:`dpnp.sum`.
1274+
Refer to :obj:`dpnp.sum` for full documentation.
12751275
12761276
"""
12771277

@@ -1289,7 +1289,7 @@ def swapaxes(self, axis1, axis2):
12891289
"""
12901290
Interchange two axes of an array.
12911291
1292-
For full documentation refer to :obj:`numpy.swapaxes`.
1292+
Refer to :obj:`dpnp.swapaxes` for full documentation.
12931293
12941294
"""
12951295

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

dpnp/dpnp_iface_mathematical.py

Lines changed: 78 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -855,42 +855,100 @@ def cumprod(x1, **kwargs):
855855
return call_origin(numpy.cumprod, x1, **kwargs)
856856

857857

858-
def cumsum(x1, **kwargs):
858+
def cumsum(a, axis=None, dtype=None, out=None):
859859
"""
860860
Return the cumulative sum of the elements along a given axis.
861861
862862
For full documentation refer to :obj:`numpy.cumsum`.
863863
864-
Limitations
865-
-----------
866-
Parameter `x` is supported as :obj:`dpnp.ndarray`.
867-
Keyword argument `kwargs` is currently unsupported.
868-
Otherwise the function will be executed sequentially on CPU.
869-
Input array data types are limited by supported DPNP :ref:`Data types`.
864+
Parameters
865+
----------
866+
a : {dpnp.ndarray, usm_ndarray}
867+
Input array.
868+
axis : int, optional
869+
Axis along which the cumulative sum is computed. The default (``None``)
870+
is to compute the cumsum over the flattened array.
871+
dtype : dtype, optional
872+
Type of the returned array and of the accumulator in which the elements
873+
are summed. If `dtype` is not specified, it defaults to the dtype of
874+
`a`, unless `a` has an integer dtype with a precision less than that of
875+
the default platform integer. In that case, the default platform
876+
integer is used.
877+
out : {dpnp.ndarray, usm_ndarray}, optional
878+
Alternative output array in which to place the result. It must have the
879+
same shape and buffer length as the expected output but the type will
880+
be cast if necessary.
881+
882+
Returns
883+
-------
884+
out : dpnp.ndarray
885+
A new array holding the result is returned unless `out` is specified as
886+
:class:`dpnp.ndarray`, in which case a reference to `out` is returned.
887+
The result has the same size as `a`, and the same shape as `a` if `axis`
888+
is not ``None`` or `a` is a 1-d array.
870889
871890
See Also
872891
--------
873-
:obj:`dpnp.diff` : Calculate the n-th discrete difference along the given axis.
892+
:obj:`dpnp.sum` : Sum array elements.
893+
:obj:`dpnp.diff` : Calculate the n-th discrete difference along given axis.
874894
875895
Examples
876896
--------
877897
>>> import dpnp as np
878-
>>> a = np.array([1, 2, 4])
879-
>>> result = np.cumsum(a)
880-
>>> [x for x in result]
881-
[1, 2, 7]
882-
>>> b = np.array([[1, 2, 3], [4, 5, 6]])
883-
>>> result = np.cumsum(b)
884-
>>> [x for x in result]
885-
[1, 2, 6, 10, 15, 21]
898+
>>> a = np.array([[1, 2, 3], [4, 5, 6]])
899+
>>> a
900+
array([[1, 2, 3],
901+
[4, 5, 6]])
902+
>>> np.cumsum(a)
903+
array([ 1, 3, 6, 10, 15, 21])
904+
>>> np.cumsum(a, dtype=float) # specifies type of output value(s)
905+
array([ 1., 3., 6., 10., 15., 21.])
906+
907+
>>> np.cumsum(a, axis=0) # sum over rows for each of the 3 columns
908+
array([[1, 2, 3],
909+
[5, 7, 9]])
910+
>>> np.cumsum(a, axis=1) # sum over columns for each of the 2 rows
911+
array([[ 1, 3, 6],
912+
[ 4, 9, 15]])
913+
914+
``cumsum(b)[-1]`` may not be equal to ``sum(b)``
915+
916+
>>> b = np.array([1, 2e-9, 3e-9] * 10000)
917+
>>> b.cumsum().dtype == b.sum().dtype == np.float64
918+
True
919+
>>> b.cumsum()[-1] == b.sum()
920+
array(False)
886921
887922
"""
888923

889-
x1_desc = dpnp.get_dpnp_descriptor(x1, copy_when_nondefault_queue=False)
890-
if x1_desc and not kwargs:
891-
return dpnp_cumsum(x1_desc).get_pyobj()
924+
dpnp.check_supported_arrays_type(a)
925+
if a.ndim > 1 and axis is None:
926+
usm_a = dpnp.ravel(a).get_array()
927+
else:
928+
usm_a = dpnp.get_usm_ndarray(a)
929+
930+
input_out = out
931+
if out is None:
932+
usm_out = None
933+
else:
934+
dpnp.check_supported_arrays_type(out)
935+
936+
# get dtype used by dpctl for result array in cumulative_sum
937+
if dtype is None:
938+
res_dt = dtu._default_accumulation_dtype(a.dtype, a.sycl_queue)
939+
else:
940+
res_dt = dpnp.dtype(dtype)
941+
res_dt = dtu._to_device_supported_dtype(res_dt, a.sycl_device)
942+
943+
# dpctl requires strict data type matching of out array with the result
944+
if out.dtype != res_dt:
945+
out = dpnp.astype(out, dtype=res_dt, copy=False)
946+
947+
usm_out = dpnp.get_usm_ndarray(out)
892948

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

895953

896954
def diff(a, n=1, axis=-1, prepend=None, append=None):

tests/helper.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,10 @@ def assert_dtype_allclose(
3737
"""
3838

3939
list_64bit_types = [numpy.float64, numpy.complex128]
40-
is_inexact = lambda x: dpnp.issubdtype(x.dtype, dpnp.inexact)
40+
is_inexact = lambda x: hasattr(x, "dtype") and dpnp.issubdtype(
41+
x.dtype, dpnp.inexact
42+
)
43+
4144
if is_inexact(dpnp_arr) or is_inexact(numpy_arr):
4245
tol_dpnp = (
4346
dpnp.finfo(dpnp_arr).resolution
@@ -73,7 +76,7 @@ def assert_dtype_allclose(
7376
assert dpnp_arr_dtype.kind == numpy_arr_dtype.kind
7477
else:
7578
assert_array_equal(dpnp_arr.asnumpy(), numpy_arr)
76-
if check_type:
79+
if check_type and hasattr(numpy_arr, "dtype"):
7780
if check_only_type_kind:
7881
assert dpnp_arr.dtype.kind == numpy_arr.dtype.kind
7982
else:

tests/skipped_tests.tbl

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -479,21 +479,6 @@ tests/third_party/cupy/math_tests/test_misc.py::TestConvolve::test_convolve_diff
479479

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

482-
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumprod::test_ndarray_cumprod_2dim_with_axis
483-
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumprod::test_cumprod_arraylike
484-
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumprod::test_cumprod_huge_array
485-
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumprod::test_cumprod_numpy_array
486-
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumprod::test_cumprod_out_noncontiguous
487-
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumprod::test_cumprod_1dim
488-
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumprod::test_cumprod_2dim_without_axis
489-
490-
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumsum::test_cumsum_arraylike[_param_0_{axis=0}]
491-
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumsum::test_cumsum_arraylike[_param_1_{axis=1}]
492-
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumsum::test_cumsum_arraylike[_param_2_{axis=2}]
493-
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumsum::test_cumsum_numpy_array[_param_0_{axis=0}]
494-
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumsum::test_cumsum_numpy_array[_param_1_{axis=1}]
495-
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumsum::test_cumsum_numpy_array[_param_2_{axis=2}]
496-
497482
tests/third_party/cupy/math_tests/test_trigonometric.py::TestUnwrap::test_unwrap_1dim
498483
tests/third_party/cupy/math_tests/test_trigonometric.py::TestUnwrap::test_unwrap_1dim_with_discont
499484
tests/third_party/cupy/math_tests/test_trigonometric.py::TestUnwrap::test_unwrap_1dim_with_period

tests/skipped_tests_gpu.tbl

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -586,28 +586,6 @@ tests/third_party/cupy/math_tests/test_misc.py::TestConvolve::test_convolve_diff
586586

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

589-
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumprod::test_ndarray_cumprod_2dim_with_axis
590-
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumprod::test_cumprod_arraylike
591-
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumprod::test_cumprod_huge_array
592-
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumprod::test_cumprod_numpy_array
593-
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumprod::test_cumprod_out_noncontiguous
594-
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumprod::test_cumprod_1dim
595-
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumprod::test_cumprod_2dim_without_axis
596-
597-
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumsum::test_cumsum[_param_0_{axis=0}]
598-
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumsum::test_cumsum[_param_1_{axis=1}]
599-
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumsum::test_cumsum[_param_2_{axis=2}]
600-
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumsum::test_cumsum_2dim[_param_0_{axis=0}]
601-
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumsum::test_cumsum_2dim[_param_1_{axis=1}]
602-
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumsum::test_cumsum_2dim[_param_2_{axis=2}]
603-
604-
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumsum::test_cumsum_arraylike[_param_0_{axis=0}]
605-
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumsum::test_cumsum_arraylike[_param_1_{axis=1}]
606-
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumsum::test_cumsum_arraylike[_param_2_{axis=2}]
607-
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumsum::test_cumsum_numpy_array[_param_0_{axis=0}]
608-
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumsum::test_cumsum_numpy_array[_param_1_{axis=1}]
609-
tests/third_party/cupy/math_tests/test_sumprod.py::TestCumsum::test_cumsum_numpy_array[_param_2_{axis=2}]
610-
611589
tests/third_party/cupy/math_tests/test_trigonometric.py::TestUnwrap::test_unwrap_1dim
612590
tests/third_party/cupy/math_tests/test_trigonometric.py::TestUnwrap::test_unwrap_1dim_with_discont
613591
tests/third_party/cupy/math_tests/test_trigonometric.py::TestUnwrap::test_unwrap_1dim_with_period

0 commit comments

Comments
 (0)