Skip to content

Commit 6716583

Browse files
authored
Merge branch 'master' into build_target_cuda
2 parents 7352c99 + cfaae8c commit 6716583

23 files changed

+572
-154
lines changed

.github/workflows/conda-package.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,13 +144,13 @@ jobs:
144144
run: conda build --no-test --python ${{ matrix.python }} --numpy 1.24 ${{ env.CHANNELS }} conda-recipe
145145

146146
- name: Upload artifact
147-
uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4
147+
uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
148148
with:
149149
name: ${{ env.PACKAGE_NAME }} ${{ runner.os }} Python ${{ matrix.python }}
150150
path: ${{ env.CONDA_BLD }}${{ env.PACKAGE_NAME }}-*.tar.bz2
151151

152152
- name: Upload wheels artifact
153-
uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4
153+
uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
154154
with:
155155
name: ${{ env.PACKAGE_NAME }} ${{ runner.os }} Wheels Python ${{ matrix.python }}
156156
path: ${{ env.WHEELS_OUTPUT_FOLDER }}${{ env.PACKAGE_NAME }}-*.whl

.github/workflows/openssf-scorecard.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ jobs:
6060
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
6161
# format to the repository Actions tab.
6262
- name: "Upload artifact"
63-
uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4
63+
uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
6464
with:
6565
name: SARIF file
6666
path: results.sarif

doc/reference/ufunc.rst

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,27 @@ Math operations
2020
dpnp.add
2121
dpnp.subtract
2222
dpnp.multiply
23+
dpnp.matmul
2324
dpnp.divide
2425
dpnp.logaddexp
2526
dpnp.logaddexp2
2627
dpnp.true_divide
2728
dpnp.floor_divide
2829
dpnp.negative
30+
dpnp.positive
2931
dpnp.power
32+
dpnp.float_power
3033
dpnp.remainder
3134
dpnp.mod
3235
dpnp.fmod
33-
dpnp.abs
36+
dpnp.divmod
3437
dpnp.absolute
3538
dpnp.fabs
3639
dpnp.rint
3740
dpnp.sign
41+
dpnp.heaviside
42+
dpnp.conj
43+
dpnp.conjugate
3844
dpnp.exp
3945
dpnp.exp2
4046
dpnp.log
@@ -44,13 +50,24 @@ Math operations
4450
dpnp.log1p
4551
dpnp.proj
4652
dpnp.sqrt
47-
dpnp.cbrt
4853
dpnp.square
54+
dpnp.cbrt
4955
dpnp.reciprocal
5056
dpnp.rsqrt
5157
dpnp.gcd
5258
dpnp.lcm
5359

60+
.. tip::
61+
62+
The optional output arguments can be used to help you save memory
63+
for large calculations. If your arrays are large, complicated
64+
expressions can take longer than absolutely necessary due to the
65+
creation and (later) destruction of temporary calculation
66+
spaces. For example, the expression ``G = A * B + C`` is equivalent to
67+
``T1 = A * B; G = T1 + C; del T1``. It will be more quickly executed
68+
as ``G = A * B; add(G, C, G)`` which is the same as
69+
``G = A * B; G += C``.
70+
5471

5572
Trigonometric functions
5673
~~~~~~~~~~~~~~~~~~~~~~~

dpnp/backend/extensions/ufunc/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ set(_elementwise_sources
2727
${CMAKE_CURRENT_SOURCE_DIR}/elementwise_functions/common.cpp
2828
${CMAKE_CURRENT_SOURCE_DIR}/elementwise_functions/degrees.cpp
2929
${CMAKE_CURRENT_SOURCE_DIR}/elementwise_functions/fabs.cpp
30+
${CMAKE_CURRENT_SOURCE_DIR}/elementwise_functions/float_power.cpp
3031
${CMAKE_CURRENT_SOURCE_DIR}/elementwise_functions/fmax.cpp
3132
${CMAKE_CURRENT_SOURCE_DIR}/elementwise_functions/fmin.cpp
3233
${CMAKE_CURRENT_SOURCE_DIR}/elementwise_functions/fmod.cpp

dpnp/backend/extensions/ufunc/elementwise_functions/common.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
#include "degrees.hpp"
2929
#include "fabs.hpp"
30+
#include "float_power.hpp"
3031
#include "fmax.hpp"
3132
#include "fmin.hpp"
3233
#include "fmod.hpp"
@@ -44,6 +45,7 @@ void init_elementwise_functions(py::module_ m)
4445
{
4546
init_degrees(m);
4647
init_fabs(m);
48+
init_float_power(m);
4749
init_fmax(m);
4850
init_fmin(m);
4951
init_fmod(m);
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
//*****************************************************************************
2+
// Copyright (c) 2024, Intel Corporation
3+
// All rights reserved.
4+
//
5+
// Redistribution and use in source and binary forms, with or without
6+
// maxification, are permitted provided that the following conditions are met:
7+
// - Redistributions of source code must retain the above copyright notice,
8+
// this list of conditions and the following disclaimer.
9+
// - Redistributions in binary form must reproduce the above copyright notice,
10+
// this list of conditions and the following disclaimer in the documentation
11+
// and/or other materials provided with the distribution.
12+
//
13+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14+
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15+
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16+
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
17+
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18+
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19+
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20+
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21+
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22+
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23+
// THE POSSIBILITY OF SUCH DAMAGE.
24+
//*****************************************************************************
25+
26+
#include <sycl/sycl.hpp>
27+
28+
#include "dpctl4pybind11.hpp"
29+
30+
#include "float_power.hpp"
31+
32+
// include a local copy of elementwise common header from dpctl tensor:
33+
// dpctl/tensor/libtensor/source/elementwise_functions/elementwise_functions.hpp
34+
// TODO: replace by including dpctl header once available
35+
#include "../../elementwise_functions/elementwise_functions.hpp"
36+
37+
// dpctl tensor headers
38+
#include "utils/type_dispatch.hpp"
39+
40+
namespace dpnp::extensions::ufunc
41+
{
42+
namespace py = pybind11;
43+
namespace py_int = dpnp::extensions::py_internal;
44+
45+
namespace impl
46+
{
47+
namespace td_ns = dpctl::tensor::type_dispatch;
48+
49+
// Supports only float and complex types
50+
template <typename T1, typename T2>
51+
struct OutputType
52+
{
53+
using value_type = typename std::disjunction<
54+
td_ns::BinaryTypeMapResultEntry<T1, float, T2, float, float>,
55+
td_ns::BinaryTypeMapResultEntry<T1, double, T2, double, double>,
56+
td_ns::BinaryTypeMapResultEntry<T1,
57+
std::complex<float>,
58+
T2,
59+
std::complex<float>,
60+
std::complex<float>>,
61+
td_ns::BinaryTypeMapResultEntry<T1,
62+
std::complex<double>,
63+
T2,
64+
std::complex<double>,
65+
std::complex<double>>,
66+
td_ns::DefaultResultEntry<void>>::result_type;
67+
};
68+
69+
static int float_power_output_typeid_table[td_ns::num_types][td_ns::num_types];
70+
71+
template <typename fnT, typename T1, typename T2>
72+
struct TypeMapFactory
73+
{
74+
std::enable_if_t<std::is_same<fnT, int>::value, int> get()
75+
{
76+
using rT = typename OutputType<T1, T2>::value_type;
77+
return td_ns::GetTypeid<rT>{}.get();
78+
}
79+
};
80+
81+
void populate_float_power_dispatch_tables(void)
82+
{
83+
td_ns::DispatchTableBuilder<int, TypeMapFactory, td_ns::num_types> dvb;
84+
dvb.populate_dispatch_table(float_power_output_typeid_table);
85+
}
86+
} // namespace impl
87+
88+
void init_float_power(py::module_ m)
89+
{
90+
impl::populate_float_power_dispatch_tables();
91+
using impl::float_power_output_typeid_table;
92+
93+
auto float_power_result_type_pyapi = [&](const py::dtype &dtype1,
94+
const py::dtype &dtype2) {
95+
return py_int::py_binary_ufunc_result_type(
96+
dtype1, dtype2, float_power_output_typeid_table);
97+
};
98+
m.def("_float_power_result_type", float_power_result_type_pyapi);
99+
}
100+
} // namespace dpnp::extensions::ufunc
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
//*****************************************************************************
2+
// Copyright (c) 2024, Intel Corporation
3+
// All rights reserved.
4+
//
5+
// Redistribution and use in source and binary forms, with or without
6+
// modification, are permitted provided that the following conditions are met:
7+
// - Redistributions of source code must retain the above copyright notice,
8+
// this list of conditions and the following disclaimer.
9+
// - Redistributions in binary form must reproduce the above copyright notice,
10+
// this list of conditions and the following disclaimer in the documentation
11+
// and/or other materials provided with the distribution.
12+
//
13+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14+
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15+
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16+
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
17+
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18+
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19+
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20+
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21+
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22+
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23+
// THE POSSIBILITY OF SUCH DAMAGE.
24+
//*****************************************************************************
25+
26+
#pragma once
27+
28+
#include <pybind11/pybind11.h>
29+
30+
namespace py = pybind11;
31+
32+
namespace dpnp::extensions::ufunc
33+
{
34+
void init_float_power(py::module_ m);
35+
} // namespace dpnp::extensions::ufunc

dpnp/dpnp_iface.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -654,7 +654,7 @@ def get_result_array(a, out=None, casting="safe"):
654654
655655
Parameters
656656
----------
657-
a : {dpnp_array}
657+
a : {dpnp.ndarray, usm_ndarray}
658658
Input array.
659659
out : {dpnp.ndarray, usm_ndarray}
660660
If provided, value of `a` array will be copied into it
@@ -671,6 +671,8 @@ def get_result_array(a, out=None, casting="safe"):
671671
"""
672672

673673
if out is None:
674+
if isinstance(a, dpt.usm_ndarray):
675+
return dpnp_array._create_from_usm_ndarray(a)
674676
return a
675677

676678
if isinstance(out, dpt.usm_ndarray):

dpnp/dpnp_iface_counting.py

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -44,25 +44,38 @@
4444
__all__ = ["count_nonzero"]
4545

4646

47-
def count_nonzero(a, axis=None, *, keepdims=False):
47+
def count_nonzero(a, axis=None, *, keepdims=False, out=None):
4848
"""
4949
Counts the number of non-zero values in the array `a`.
5050
5151
For full documentation refer to :obj:`numpy.count_nonzero`.
5252
53+
Parameters
54+
----------
55+
a : {dpnp.ndarray, usm_ndarray}
56+
The array for which to count non-zeros.
57+
axis : {None, int, tuple}, optional
58+
Axis or tuple of axes along which to count non-zeros.
59+
Default value means that non-zeros will be counted along a flattened
60+
version of `a`.
61+
Default: ``None``.
62+
keepdims : bool, optional
63+
If this is set to ``True``, the axes that are counted are left in the
64+
result as dimensions with size one. With this option, the result will
65+
broadcast correctly against the input array.
66+
Default: ``False``.
67+
out : {None, dpnp.ndarray, usm_ndarray}, optional
68+
The array into which the result is written. The data type of `out` must
69+
match the expected shape and the expected data type of the result.
70+
If ``None`` then a new array is returned.
71+
Default: ``None``.
72+
5373
Returns
5474
-------
5575
out : dpnp.ndarray
5676
Number of non-zero values in the array along a given axis.
57-
Otherwise, a zero-dimensional array with the total number of
58-
non-zero values in the array is returned.
59-
60-
Limitations
61-
-----------
62-
Parameters `a` is supported as either :class:`dpnp.ndarray`
63-
or :class:`dpctl.tensor.usm_ndarray`.
64-
Otherwise ``TypeError`` exception will be raised.
65-
Input array data types are limited by supported DPNP :ref:`Data types`.
77+
Otherwise, a zero-dimensional array with the total number of non-zero
78+
values in the array is returned.
6679
6780
See Also
6881
--------
@@ -87,8 +100,10 @@ def count_nonzero(a, axis=None, *, keepdims=False):
87100
88101
"""
89102

90-
# TODO: might be improved by implementing an extension
91-
# with `count_nonzero` kernel
92103
usm_a = dpnp.get_usm_ndarray(a)
93-
usm_a = dpt.astype(usm_a, dpnp.bool, copy=False)
94-
return dpnp.sum(usm_a, axis=axis, dtype=dpnp.intp, keepdims=keepdims)
104+
usm_out = None if out is None else dpnp.get_usm_ndarray(out)
105+
106+
usm_res = dpt.count_nonzero(
107+
usm_a, axis=axis, keepdims=keepdims, out=usm_out
108+
)
109+
return dpnp.get_result_array(usm_res, out)

dpnp/dpnp_iface_logic.py

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@
5151

5252
import dpnp
5353
from dpnp.dpnp_algo.dpnp_elementwise_common import DPNPBinaryFunc, DPNPUnaryFunc
54-
from dpnp.dpnp_array import dpnp_array
5554

5655
__all__ = [
5756
"all",
@@ -167,13 +166,11 @@ def all(a, /, axis=None, out=None, keepdims=False, *, where=True):
167166

168167
dpnp.check_limitations(where=where)
169168

170-
dpt_array = dpnp.get_usm_ndarray(a)
171-
result = dpnp_array._create_from_usm_ndarray(
172-
dpt.all(dpt_array, axis=axis, keepdims=keepdims)
173-
)
169+
usm_a = dpnp.get_usm_ndarray(a)
170+
usm_res = dpt.all(usm_a, axis=axis, keepdims=keepdims)
171+
174172
# TODO: temporary solution until dpt.all supports out parameter
175-
result = dpnp.get_result_array(result, out)
176-
return result
173+
return dpnp.get_result_array(usm_res, out)
177174

178175

179176
def allclose(a, b, rtol=1.0e-5, atol=1.0e-8, equal_nan=False):
@@ -333,13 +330,11 @@ def any(a, /, axis=None, out=None, keepdims=False, *, where=True):
333330

334331
dpnp.check_limitations(where=where)
335332

336-
dpt_array = dpnp.get_usm_ndarray(a)
337-
result = dpnp_array._create_from_usm_ndarray(
338-
dpt.any(dpt_array, axis=axis, keepdims=keepdims)
339-
)
333+
usm_a = dpnp.get_usm_ndarray(a)
334+
usm_res = dpt.any(usm_a, axis=axis, keepdims=keepdims)
335+
340336
# TODO: temporary solution until dpt.any supports out parameter
341-
result = dpnp.get_result_array(result, out)
342-
return result
337+
return dpnp.get_result_array(usm_res, out)
343338

344339

345340
_EQUAL_DOCSTRING = """

0 commit comments

Comments
 (0)