Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework transpose methods to use dpctl.tensor functions #1389

Merged
merged 4 commits into from
Jun 13, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion dpnp/backend/include/dpnp_iface_fptr.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,6 @@ enum class DPNPFuncName : size_t
DPNP_FN_TANH, /**< Used in numpy.tanh() impl */
DPNP_FN_TANH_EXT, /**< Used in numpy.tanh() impl, requires extra parameters */
DPNP_FN_TRANSPOSE, /**< Used in numpy.transpose() impl */
DPNP_FN_TRANSPOSE_EXT, /**< Used in numpy.transpose() impl, requires extra parameters */
DPNP_FN_TRACE, /**< Used in numpy.trace() impl */
DPNP_FN_TRACE_EXT, /**< Used in numpy.trace() impl, requires extra parameters */
DPNP_FN_TRAPZ, /**< Used in numpy.trapz() impl */
Expand Down
24 changes: 2 additions & 22 deletions dpnp/backend/kernels/dpnp_krnl_manipulation.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//*****************************************************************************
// Copyright (c) 2016-2020, Intel Corporation
// Copyright (c) 2016-2023, Intel Corporation
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -211,6 +211,7 @@ void dpnp_elemwise_transpose_c(void* array1_in,
size,
dep_event_vec_ref);
DPCTLEvent_WaitAndThrow(event_ref);
DPCTLEvent_Delete(event_ref);
}

template <typename _DataType>
Expand All @@ -222,17 +223,6 @@ void (*dpnp_elemwise_transpose_default_c)(void*,
void*,
size_t) = dpnp_elemwise_transpose_c<_DataType>;

template <typename _DataType>
DPCTLSyclEventRef (*dpnp_elemwise_transpose_ext_c)(DPCTLSyclQueueRef,
void*,
const shape_elem_type*,
const shape_elem_type*,
const shape_elem_type*,
size_t,
void*,
size_t,
const DPCTLEventVectorRef) = dpnp_elemwise_transpose_c<_DataType>;

void func_map_init_manipulation(func_map_t& fmap)
{
fmap[DPNPFuncName::DPNP_FN_REPEAT][eft_INT][eft_INT] = {eft_INT, (void*)dpnp_repeat_default_c<int32_t>};
Expand All @@ -253,15 +243,5 @@ void func_map_init_manipulation(func_map_t& fmap)
(void*)dpnp_elemwise_transpose_default_c<float>};
fmap[DPNPFuncName::DPNP_FN_TRANSPOSE][eft_DBL][eft_DBL] = {eft_DBL,
(void*)dpnp_elemwise_transpose_default_c<double>};

fmap[DPNPFuncName::DPNP_FN_TRANSPOSE_EXT][eft_INT][eft_INT] = {eft_INT,
(void*)dpnp_elemwise_transpose_ext_c<int32_t>};
fmap[DPNPFuncName::DPNP_FN_TRANSPOSE_EXT][eft_LNG][eft_LNG] = {eft_LNG,
(void*)dpnp_elemwise_transpose_ext_c<int64_t>};
fmap[DPNPFuncName::DPNP_FN_TRANSPOSE_EXT][eft_FLT][eft_FLT] = {eft_FLT,
(void*)dpnp_elemwise_transpose_ext_c<float>};
fmap[DPNPFuncName::DPNP_FN_TRANSPOSE_EXT][eft_DBL][eft_DBL] = {eft_DBL,
(void*)dpnp_elemwise_transpose_ext_c<double>};

return;
}
2 changes: 0 additions & 2 deletions dpnp/dpnp_algo/dpnp_algo.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,6 @@ cdef extern from "dpnp_iface_fptr.hpp" namespace "DPNPFuncName": # need this na
DPNP_FN_TRACE
DPNP_FN_TRACE_EXT
DPNP_FN_TRANSPOSE
DPNP_FN_TRANSPOSE_EXT
DPNP_FN_TRAPZ
DPNP_FN_TRAPZ_EXT
DPNP_FN_TRI
Expand Down Expand Up @@ -555,7 +554,6 @@ cpdef dpnp_descriptor dpnp_subtract(dpnp_descriptor x1_obj, dpnp_descriptor x2_o
Array manipulation routines
"""
cpdef dpnp_descriptor dpnp_repeat(dpnp_descriptor array1, repeats, axes=*)
cpdef dpnp_descriptor dpnp_transpose(dpnp_descriptor array1, axes=*)


"""
Expand Down
74 changes: 0 additions & 74 deletions dpnp/dpnp_algo/dpnp_algo_manipulation.pxi
Original file line number Diff line number Diff line change
Expand Up @@ -42,21 +42,11 @@ __all__ += [
"dpnp_expand_dims",
"dpnp_repeat",
"dpnp_reshape",
"dpnp_transpose",
"dpnp_squeeze",
]


# C function pointer to the C library template functions
ctypedef c_dpctl.DPCTLSyclEventRef(*fptr_custom_elemwise_transpose_1in_1out_t)(c_dpctl.DPCTLSyclQueueRef,
void * ,
shape_elem_type * ,
shape_elem_type * ,
shape_elem_type * ,
size_t,
void * ,
size_t,
const c_dpctl.DPCTLEventVectorRef)
ctypedef c_dpctl.DPCTLSyclEventRef(*fptr_dpnp_repeat_t)(c_dpctl.DPCTLSyclQueueRef,
const void *, void * , const size_t , const size_t,
const c_dpctl.DPCTLEventVectorRef)
Expand Down Expand Up @@ -232,70 +222,6 @@ cpdef utils.dpnp_descriptor dpnp_reshape(utils.dpnp_descriptor array1, newshape,
copy_when_nondefault_queue=False)


cpdef utils.dpnp_descriptor dpnp_transpose(utils.dpnp_descriptor array1, axes=None):
cdef shape_type_c input_shape = array1.shape
cdef size_t input_shape_size = array1.ndim
cdef shape_type_c result_shape = shape_type_c(input_shape_size, 1)

cdef shape_type_c permute_axes
if axes is None:
"""
template to do transpose a tensor
input_shape=[2, 3, 4]
permute_axes=[2, 1, 0]
after application `permute_axes` to `input_shape` result:
result_shape=[4, 3, 2]

'do nothing' axes variable is `permute_axes=[0, 1, 2]`

test: pytest tests/third_party/cupy/manipulation_tests/test_transpose.py::TestTranspose::test_external_transpose_all
"""
permute_axes = list(reversed([i for i in range(input_shape_size)]))
else:
permute_axes = utils.normalize_axis(axes, input_shape_size)

for i in range(input_shape_size):
""" construct output shape """
result_shape[i] = input_shape[permute_axes[i]]

# convert string type names (array.dtype) to C enum DPNPFuncType
cdef DPNPFuncType param1_type = dpnp_dtype_to_DPNPFuncType(array1.dtype)

# get the FPTR data structure
cdef DPNPFuncData kernel_data = get_dpnp_function_ptr(DPNP_FN_TRANSPOSE_EXT, param1_type, param1_type)

array1_obj = array1.get_array()

# ceate result array with type given by FPTR data
cdef utils.dpnp_descriptor result = utils.create_output_descriptor(result_shape,
kernel_data.return_type,
None,
device=array1_obj.sycl_device,
usm_type=array1_obj.usm_type,
sycl_queue=array1_obj.sycl_queue)
result_sycl_queue = result.get_array().sycl_queue

cdef c_dpctl.SyclQueue q = <c_dpctl.SyclQueue> result_sycl_queue
cdef c_dpctl.DPCTLSyclQueueRef q_ref = q.get_queue_ref()

cdef fptr_custom_elemwise_transpose_1in_1out_t func = <fptr_custom_elemwise_transpose_1in_1out_t > kernel_data.ptr
# call FPTR function
cdef c_dpctl.DPCTLSyclEventRef event_ref = func(q_ref,
array1.get_data(),
input_shape.data(),
result_shape.data(),
permute_axes.data(),
input_shape_size,
result.get_data(),
array1.size,
NULL) # dep_events_ref

with nogil: c_dpctl.DPCTLEvent_WaitAndThrow(event_ref)
c_dpctl.DPCTLEvent_Delete(event_ref)

return result


cpdef utils.dpnp_descriptor dpnp_squeeze(utils.dpnp_descriptor in_array, axis):
cdef shape_type_c shape_list
if axis is None:
Expand Down
68 changes: 54 additions & 14 deletions dpnp/dpnp_array.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,15 +99,8 @@ def get_array(self):

@property
def T(self):
"""Shape-reversed view of the array.

If ndim < 2, then this is just a reference to the array itself.

"""
if self.ndim < 2:
return self
else:
return dpnp.transpose(self)
"""View of the transposed array."""
return self.transpose()

def to_device(self, target_device):
"""
Expand Down Expand Up @@ -1000,15 +993,62 @@ def take(self, indices, axis=None, out=None, mode='raise'):

def transpose(self, *axes):
"""
Returns a view of the array with axes permuted.
Returns a view of the array with axes transposed.

.. seealso::
:obj:`dpnp.transpose` for full documentation,
:meth:`numpy.ndarray.reshape`
For full documentation refer to :obj:`numpy.ndarray.transpose`.

Returns
-------
y : dpnp.ndarray
View of the array with its axes suitably permuted.

See Also
--------
:obj:`dpnp.transpose` : Equivalent function.
:obj:`dpnp.ndarray.ndarray.T` : Array property returning the array transposed.
:obj:`dpnp.ndarray.reshape` : Give a new shape to an array without changing its data.

Examples
--------
>>> import dpnp as dp
>>> a = dp.array([[1, 2], [3, 4]])
>>> a
array([[1, 2],
[3, 4]])
>>> a.transpose()
array([[1, 3],
[2, 4]])
>>> a.transpose((1, 0))
array([[1, 3],
[2, 4]])

>>> a = dp.array([1, 2, 3, 4])
>>> a
array([1, 2, 3, 4])
>>> a.transpose()
array([1, 2, 3, 4])

"""

return dpnp.transpose(self, axes)
ndim = self.ndim
if ndim < 2:
return self

axes_len = len(axes)
if axes_len == 1 and isinstance(axes[0], tuple):
axes = axes[0]

res = self.__new__(dpnp_array)
if ndim == 2 and axes_len == 0:
res._array_obj = self._array_obj.T
else:
if len(axes) == 0 or axes[0] is None:
# self.transpose().shape == self.shape[::-1]
# self.transpose(None).shape == self.shape[::-1]
axes = tuple((ndim - x - 1) for x in range(ndim))

res._array_obj = dpt.permute_dims(self._array_obj, axes)
antonwolfy marked this conversation as resolved.
Show resolved Hide resolved
return res

def var(self, axis=None, dtype=None, out=None, ddof=0, keepdims=False):
"""
Expand Down
79 changes: 45 additions & 34 deletions dpnp/dpnp_iface_manipulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -678,54 +678,65 @@ def swapaxes(x1, axis1, axis2):
return call_origin(numpy.swapaxes, x1, axis1, axis2)


def transpose(x1, axes=None):
def transpose(a, axes=None):
"""
Reverse or permute the axes of an array; returns the modified array.
Returns an array with axes transposed.

For full documentation refer to :obj:`numpy.transpose`.

Returns
-------
y : dpnp.ndarray
`a` with its axes permuted. A view is returned whenever possible.

Limitations
-----------
Input array is supported as :obj:`dpnp.ndarray`.
Otherwise the function will be executed sequentially on CPU.
Value of the parameter ``axes`` likely to be replaced with ``None``.
Input array data types are limited by supported DPNP :ref:`Data types`.
Input array is supported as either :class:`dpnp.ndarray`
or :class:`dpctl.tensor.usm_ndarray`.

See Also
--------
:obj:`dpnp.ndarray.transpose` : Equivalent method.
:obj:`dpnp.moveaxis` : Move array axes to new positions.
:obj:`dpnp.argsort` : Returns the indices that would sort an array.

Examples
--------
>>> import dpnp as np
>>> x = np.arange(4).reshape((2,2))
>>> x.shape
(2, 2)
>>> [i for i in x]
[0, 1, 2, 3]
>>> out = np.transpose(x)
>>> out.shape
(2, 2)
>>> [i for i in out]
[0, 2, 1, 3]

"""

x1_desc = dpnp.get_dpnp_descriptor(x1, copy_when_nondefault_queue=False)
if x1_desc:
if axes is not None:
if not any(axes):
"""
pytest tests/third_party/cupy/manipulation_tests/test_transpose.py
"""
axes = None

result = dpnp_transpose(x1_desc, axes).get_pyobj()

return result

return call_origin(numpy.transpose, x1, axes=axes)
>>> import dpnp as dp
>>> a = dp.array([[1, 2], [3, 4]])
>>> a
array([[1, 2],
[3, 4]])
>>> dp.transpose(a)
array([[1, 3],
[2, 4]])

>>> a = dp.array([1, 2, 3, 4])
>>> a
array([1, 2, 3, 4])
>>> dp.transpose(a)
array([1, 2, 3, 4])

>>> a = dp.ones((1, 2, 3))
>>> dp.transpose(a, (1, 0, 2)).shape
(2, 1, 3)

>>> a = dp.ones((2, 3, 4, 5))
>>> dp.transpose(a).shape
(5, 4, 3, 2)

"""

if isinstance(a, dpnp_array):
array = a
elif isinstance(a, dpt.usm_ndarray):
array = dpnp_array._create_from_usm_ndarray(a.get_array())
else:
raise TypeError("An array must be any of supported type, but got {}".format(type(a)))

if axes is None:
return array.transpose()
return array.transpose(*axes)


def unique(x1, **kwargs):
Expand Down
3 changes: 1 addition & 2 deletions dpnp/dpnp_iface_statistics.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,8 +290,7 @@ def cov(x1, y=None, rowvar=True, bias=False, ddof=None, fweights=None, aweights=
pass
else:
if not rowvar and x1.shape[0] != 1:
x1 = x1.get_array() if isinstance(x1, dpnp_array) else x1
x1 = dpnp_array._create_from_usm_ndarray(x1.mT)
x1 = x1.T

if not x1.dtype in (dpnp.float32, dpnp.float64):
x1 = dpnp.astype(x1, dpnp.default_float_type(sycl_queue=x1.sycl_queue))
Expand Down
4 changes: 0 additions & 4 deletions tests/skipped_tests.tbl
Original file line number Diff line number Diff line change
Expand Up @@ -234,8 +234,6 @@ tests/third_party/cupy/core_tests/test_ndarray_copy_and_view.py::TestArrayCopyAn
tests/third_party/cupy/core_tests/test_ndarray_copy_and_view.py::TestArrayCopyAndView::test_astype_strides_swapped
tests/third_party/cupy/core_tests/test_ndarray_copy_and_view.py::TestArrayCopyAndView::test_astype_type_c_contiguous_no_copy
tests/third_party/cupy/core_tests/test_ndarray_copy_and_view.py::TestArrayCopyAndView::test_astype_type_f_contiguous_no_copy
tests/third_party/cupy/core_tests/test_ndarray_copy_and_view.py::TestArrayCopyAndView::test_transposed_fill
tests/third_party/cupy/core_tests/test_ndarray_copy_and_view.py::TestArrayCopyAndView::test_transposed_flatten
tests/third_party/cupy/core_tests/test_ndarray_copy_and_view.py::TestArrayCopyAndView::test_flatten
tests/third_party/cupy/core_tests/test_ndarray_copy_and_view.py::TestArrayCopyAndView::test_flatten_copied
tests/third_party/cupy/core_tests/test_ndarray_copy_and_view.py::TestArrayCopyAndView::test_isinstance_numpy_copy
Expand Down Expand Up @@ -837,7 +835,6 @@ tests/third_party/cupy/math_tests/test_rounding.py::TestRounding::test_rint_nega
tests/third_party/cupy/math_tests/test_sumprod.py::TestSumprod::test_sum_all
tests/third_party/cupy/math_tests/test_sumprod.py::TestSumprod::test_sum_all2
tests/third_party/cupy/math_tests/test_sumprod.py::TestSumprod::test_sum_all_keepdims
tests/third_party/cupy/math_tests/test_sumprod.py::TestSumprod::test_sum_all_transposed
tests/third_party/cupy/math_tests/test_sumprod.py::TestSumprod::test_sum_all_transposed2
tests/third_party/cupy/math_tests/test_sumprod.py::TestSumprod::test_sum_axes
tests/third_party/cupy/math_tests/test_sumprod.py::TestSumprod::test_sum_axes2
Expand Down Expand Up @@ -886,7 +883,6 @@ tests/third_party/cupy/math_tests/test_sumprod.py::TestNansumNanprodLong_param_1
tests/third_party/cupy/math_tests/test_sumprod.py::TestNansumNanprodLong_param_9_{axis=0, func='nanprod', keepdims=True, shape=(2, 3, 4), transpose_axes=False}::test_nansum_all
tests/third_party/cupy/math_tests/test_sumprod.py::TestNansumNanprodLong_param_9_{axis=0, func='nanprod', keepdims=True, shape=(2, 3, 4), transpose_axes=False}::test_nansum_axis_transposed
tests/third_party/cupy/math_tests/test_sumprod.py::TestSumprod::test_sum_all2
tests/third_party/cupy/math_tests/test_sumprod.py::TestSumprod::test_sum_all_transposed2
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_2dim_with_axis
Expand Down
Loading