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

Leverage dpctl.tensor.put() implementation #1529

Merged
merged 13 commits into from
Sep 11, 2023
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 @@ -280,7 +280,6 @@ enum class DPNPFuncName : size_t
DPNP_FN_PTP, /**< Used in numpy.ptp() impl */
DPNP_FN_PTP_EXT, /**< Used in numpy.ptp() impl, requires extra parameters */
DPNP_FN_PUT, /**< Used in numpy.put() impl */
DPNP_FN_PUT_EXT, /**< Used in numpy.put() impl, requires extra parameters */
DPNP_FN_PUT_ALONG_AXIS, /**< Used in numpy.put_along_axis() impl */
DPNP_FN_PUT_ALONG_AXIS_EXT, /**< Used in numpy.put_along_axis() impl,
requires extra parameters */
Expand Down
20 changes: 0 additions & 20 deletions dpnp/backend/kernels/dpnp_krnl_indexing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -602,17 +602,6 @@ void (*dpnp_put_default_c)(void *,
const size_t) =
dpnp_put_c<_DataType, _IndecesType, _ValueType>;

template <typename _DataType, typename _IndecesType, typename _ValueType>
DPCTLSyclEventRef (*dpnp_put_ext_c)(DPCTLSyclQueueRef,
void *,
void *,
void *,
const size_t,
const size_t,
const size_t,
const DPCTLEventVectorRef) =
dpnp_put_c<_DataType, _IndecesType, _ValueType>;

template <typename _DataType>
DPCTLSyclEventRef
dpnp_put_along_axis_c(DPCTLSyclQueueRef q_ref,
Expand Down Expand Up @@ -1007,15 +996,6 @@ void func_map_init_indexing_func(func_map_t &fmap)
fmap[DPNPFuncName::DPNP_FN_PUT][eft_DBL][eft_DBL] = {
eft_DBL, (void *)dpnp_put_default_c<double, int64_t, double>};

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

fmap[DPNPFuncName::DPNP_FN_PUT_ALONG_AXIS][eft_INT][eft_INT] = {
eft_INT, (void *)dpnp_put_along_axis_default_c<int32_t>};
fmap[DPNPFuncName::DPNP_FN_PUT_ALONG_AXIS][eft_LNG][eft_LNG] = {
Expand Down
2 changes: 0 additions & 2 deletions dpnp/dpnp_algo/dpnp_algo.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,6 @@ cdef extern from "dpnp_iface_fptr.hpp" namespace "DPNPFuncName": # need this na
DPNP_FN_PROD_EXT
DPNP_FN_PTP
DPNP_FN_PTP_EXT
DPNP_FN_PUT
DPNP_FN_PUT_EXT
DPNP_FN_QR
DPNP_FN_QR_EXT
DPNP_FN_RADIANS
Expand Down
68 changes: 0 additions & 68 deletions dpnp/dpnp_algo/dpnp_algo_indexing.pxi
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ __all__ += [
"dpnp_diagonal",
"dpnp_fill_diagonal",
"dpnp_indices",
"dpnp_put",
"dpnp_put_along_axis",
"dpnp_putmask",
"dpnp_select",
Expand Down Expand Up @@ -80,14 +79,6 @@ ctypedef c_dpctl.DPCTLSyclEventRef(*custom_indexing_3in_with_axis_func_ptr_t)(c_
const size_t,
const size_t,
const c_dpctl.DPCTLEventVectorRef)
ctypedef c_dpctl.DPCTLSyclEventRef(*custom_indexing_6in_func_ptr_t)(c_dpctl.DPCTLSyclQueueRef,
void *,
void * ,
void * ,
const size_t,
const size_t,
const size_t,
const c_dpctl.DPCTLEventVectorRef)


cpdef utils.dpnp_descriptor dpnp_choose(utils.dpnp_descriptor x1, list choices1):
Expand Down Expand Up @@ -292,65 +283,6 @@ cpdef object dpnp_indices(dimensions):
return dpnp_result


cpdef dpnp_put(dpnp_descriptor x1, object ind, v):
ind_is_list = isinstance(ind, list)

x1_obj = x1.get_array()

if dpnp.isscalar(ind):
ind_size = 1
else:
ind_size = len(ind)
cdef utils.dpnp_descriptor ind_array = utils_py.create_output_descriptor_py((ind_size,),
dpnp.int64,
None,
device=x1_obj.sycl_device,
usm_type=x1_obj.usm_type,
sycl_queue=x1_obj.sycl_queue)
if dpnp.isscalar(ind):
ind_array.get_pyobj()[0] = ind
else:
for i in range(ind_size):
ind_array.get_pyobj()[i] = ind[i]

if dpnp.isscalar(v):
v_size = 1
else:
v_size = len(v)
cdef utils.dpnp_descriptor v_array = utils_py.create_output_descriptor_py((v_size,),
x1.dtype,
None,
device=x1_obj.sycl_device,
usm_type=x1_obj.usm_type,
sycl_queue=x1_obj.sycl_queue)
if dpnp.isscalar(v):
v_array.get_pyobj()[0] = v
else:
for i in range(v_size):
v_array.get_pyobj()[i] = v[i]

cdef DPNPFuncType param1_type = dpnp_dtype_to_DPNPFuncType(x1.dtype)

cdef DPNPFuncData kernel_data = get_dpnp_function_ptr(DPNP_FN_PUT_EXT, param1_type, param1_type)

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

cdef custom_indexing_6in_func_ptr_t func = <custom_indexing_6in_func_ptr_t > kernel_data.ptr

cdef c_dpctl.DPCTLSyclEventRef event_ref = func(q_ref,
x1.get_data(),
ind_array.get_data(),
v_array.get_data(),
x1.size,
ind_array.size,
v_array.size,
NULL) # dep_events_ref

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


cpdef dpnp_put_along_axis(dpnp_descriptor arr, dpnp_descriptor indices, dpnp_descriptor values, int axis):
cdef shape_type_c arr_shape = arr.shape
cdef DPNPFuncType param1_type = dpnp_dtype_to_DPNPFuncType(arr.dtype)
Expand Down
13 changes: 11 additions & 2 deletions dpnp/dpnp_array.py
Original file line number Diff line number Diff line change
Expand Up @@ -963,8 +963,17 @@ def prod(

return dpnp.prod(self, axis, dtype, out, keepdims, initial, where)

# 'ptp',
# 'put',
# 'ptp'

def put(self, indices, vals, /, *, axis=None, mode="wrap"):
vlad-perevezentsev marked this conversation as resolved.
Show resolved Hide resolved
"""
Puts values of an array into another array along a given axis.

For full documentation refer to :obj:`numpy.put`.
"""

return dpnp.put(self, indices, vals, axis=axis, mode=mode)

# 'ravel',
# 'real',
# 'repeat',
Expand Down
79 changes: 63 additions & 16 deletions dpnp/dpnp_iface_indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -417,34 +417,81 @@ def place(x, mask, vals, /):
return call_origin(numpy.place, x, mask, vals, dpnp_inplace=True)


def put(x1, ind, v, mode="raise"):
def put(a, indices, vals, /, *, axis=None, mode="wrap"):
"""
Replaces specified elements of an array with given values.
Puts values of an array into another array along a given axis.

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

Limitations
-----------
Input array is supported as :obj:`dpnp.ndarray`.
Not supported parameter mode.
Parameters `a` and `indices` are supported either as :class:`dpnp.ndarray`
or :class:`dpctl.tensor.usm_ndarray`.
Parameter `indices` is supported as 1-D array of integer data type.
Parameter `vals` must be broadcastable to the shape of `indices`
and has the same data type as `a` if it is as :class:`dpnp.ndarray`
or :class:`dpctl.tensor.usm_ndarray`.
Parameter `mode` is supported with ``wrap``, the default, and ``clip`` values.
Parameter `axis` is supported as integer only.
Otherwise the function will be executed sequentially on CPU.

See Also
--------
:obj:`dpnp.putmask` : Changes elements of an array based on conditional and input values.
:obj:`dpnp.place` : Change elements of an array based on conditional and input values.
:obj:`dpnp.put_along_axis` : Put values into the destination array by matching 1d index and data slices.

Notes
-----
In contrast to :obj:`numpy.put` `wrap` mode which wraps indices around the array for cyclic operations,
:obj:`dpnp.put` `wrap` mode clamps indices to a fixed range within the array boundaries (-n <= i < n).

Examples
--------
>>> import dpnp as np
>>> x = np.arange(5)
>>> indices = np.array([0, 1])
>>> np.put(x, indices, [-44, -55])
>>> x
array([-44, -55, 2, 3, 4])

>>> x = np.arange(5)
>>> indices = np.array([22])
>>> np.put(x, indices, -5, mode='clip')
>>> x
array([ 0, 1, 2, 3, -5])

"""
vlad-perevezentsev marked this conversation as resolved.
Show resolved Hide resolved

x1_desc = dpnp.get_dpnp_descriptor(
x1, copy_when_strides=False, copy_when_nondefault_queue=False
)
if x1_desc:
if mode != "raise":
if dpnp.is_supported_array_type(a) and dpnp.is_supported_array_type(
indices
):
if indices.ndim != 1 or not dpnp.issubdtype(
indices.dtype, dpnp.integer
):
pass
vlad-perevezentsev marked this conversation as resolved.
Show resolved Hide resolved
elif type(ind) is not type(v):
elif mode not in ("clip", "wrap"):
pass
elif (
numpy.max(ind) >= x1_desc.size or numpy.min(ind) + x1_desc.size < 0
):
elif axis is not None and not isinstance(axis, int):
raise TypeError(f"`axis` must be of integer type, got {type(axis)}")
# TODO: remove when #1382(dpctl) is solved
elif dpnp.is_supported_array_type(vals) and a.dtype != vals.dtype:
pass
antonwolfy marked this conversation as resolved.
Show resolved Hide resolved
else:
return dpnp_put(x1_desc, ind, v)
if axis is None and a.ndim > 1:
a = dpnp.reshape(a, -1)
dpt_array = dpnp.get_usm_ndarray(a)
dpt_indices = dpnp.get_usm_ndarray(indices)
dpt_vals = (
dpnp.get_usm_ndarray(vals)
if isinstance(vals, dpnp_array)
else vals
)
return dpt.put(
dpt_array, dpt_indices, dpt_vals, axis=axis, mode=mode
)

return call_origin(numpy.put, x1, ind, v, mode, dpnp_inplace=True)
return call_origin(numpy.put, a, indices, vals, mode, dpnp_inplace=True)


def put_along_axis(x1, indices, values, axis):
Expand Down Expand Up @@ -557,7 +604,7 @@ def take(x, indices, /, *, axis=None, out=None, mode="wrap"):
or :class:`dpctl.tensor.usm_ndarray`.
Parameter `indices` is supported as 1-D array of integer data type.
Parameter `out` is supported only with default value.
Parameter `mode` is supported with ``wrap``(default) and ``clip`` mode.
Parameter `mode` is supported with ``wrap``, the default, and ``clip`` values.
Providing parameter `axis` is optional when `x` is a 1-D array.
Otherwise the function will be executed sequentially on CPU.

Expand Down
Loading