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 @@ -296,7 +296,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 @@ -166,8 +166,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
78 changes: 63 additions & 15 deletions dpnp/dpnp_iface_indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -417,34 +417,82 @@ 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.
Paramenet `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``(default) and ``clip`` mode.
vlad-perevezentsev marked this conversation as resolved.
Show resolved Hide resolved
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
-----
How out-of-bounds indices will be handled.
"wrap" - clamps indices to (-n <= i < n), then wraps negative indices.
"clip" - clips indices to (0 <= 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])
vlad-perevezentsev marked this conversation as resolved.
Show resolved Hide resolved
vlad-perevezentsev marked this conversation as resolved.
Show resolved Hide resolved

>>> 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

"""
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
Loading