Skip to content

Commit 6c9037d

Browse files
committed
Add mkl_vm::copysign() extnesion to be used in dpnp.copysign
1 parent 31573f9 commit 6c9037d

File tree

5 files changed

+207
-0
lines changed

5 files changed

+207
-0
lines changed

dpnp/backend/extensions/vm/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ if(NOT _use_onemkl_interfaces)
3838
${CMAKE_CURRENT_SOURCE_DIR}/cbrt.cpp
3939
${CMAKE_CURRENT_SOURCE_DIR}/ceil.cpp
4040
${CMAKE_CURRENT_SOURCE_DIR}/conj.cpp
41+
${CMAKE_CURRENT_SOURCE_DIR}/copysign.cpp
4142
${CMAKE_CURRENT_SOURCE_DIR}/cos.cpp
4243
${CMAKE_CURRENT_SOURCE_DIR}/cosh.cpp
4344
${CMAKE_CURRENT_SOURCE_DIR}/div.cpp
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
//*****************************************************************************
2+
// Copyright (c) 2025, 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+
#include <stdexcept>
27+
28+
#include <oneapi/mkl.hpp>
29+
#include <sycl/sycl.hpp>
30+
31+
#include "dpctl4pybind11.hpp"
32+
33+
#include "common.hpp"
34+
#include "copysign.hpp"
35+
36+
// include a local copy of elementwise common header from dpctl tensor:
37+
// dpctl/tensor/libtensor/source/elementwise_functions/elementwise_functions.hpp
38+
// TODO: replace by including dpctl header once available
39+
#include "../elementwise_functions/elementwise_functions.hpp"
40+
41+
// dpctl tensor headers
42+
#include "kernels/elementwise_functions/common.hpp"
43+
#include "utils/type_dispatch.hpp"
44+
#include "utils/type_utils.hpp"
45+
46+
namespace dpnp::extensions::vm
47+
{
48+
namespace py = pybind11;
49+
namespace py_int = dpnp::extensions::py_internal;
50+
namespace td_ns = dpctl::tensor::type_dispatch;
51+
52+
namespace impl
53+
{
54+
namespace ew_cmn_ns = dpctl::tensor::kernels::elementwise_common;
55+
namespace mkl_vm = oneapi::mkl::vm; // OneMKL namespace with VM functions
56+
namespace tu_ns = dpctl::tensor::type_utils;
57+
58+
/**
59+
* @brief A factory to define pairs of supported types for which
60+
* MKL VM library provides support in oneapi::mkl::vm::copysign<T> function.
61+
*
62+
* @tparam T Type of input vectors `a` and `b` and of result vector `y`.
63+
*/
64+
template <typename T1, typename T2>
65+
struct OutputType
66+
{
67+
using value_type = typename std::disjunction<
68+
td_ns::BinaryTypeMapResultEntry<T1, double, T2, double, double>,
69+
td_ns::BinaryTypeMapResultEntry<T1, float, T2, float, float>,
70+
td_ns::DefaultResultEntry<void>>::result_type;
71+
};
72+
73+
template <typename T1, typename T2>
74+
static sycl::event copysign_contig_impl(sycl::queue &exec_q,
75+
std::size_t in_n,
76+
const char *in_a,
77+
py::ssize_t a_offset,
78+
const char *in_b,
79+
py::ssize_t b_offset,
80+
char *out_y,
81+
py::ssize_t out_offset,
82+
const std::vector<sycl::event> &depends)
83+
{
84+
tu_ns::validate_type_for_device<T1>(exec_q);
85+
tu_ns::validate_type_for_device<T2>(exec_q);
86+
87+
if ((a_offset != 0) || (b_offset != 0) || (out_offset != 0)) {
88+
throw std::runtime_error("Arrays offsets have to be equals to 0");
89+
}
90+
91+
std::int64_t n = static_cast<std::int64_t>(in_n);
92+
const T1 *a = reinterpret_cast<const T1 *>(in_a);
93+
const T2 *b = reinterpret_cast<const T2 *>(in_b);
94+
95+
using resTy = typename OutputType<T1, T2>::value_type;
96+
resTy *y = reinterpret_cast<resTy *>(out_y);
97+
98+
return mkl_vm::copysign(
99+
exec_q,
100+
n, // number of elements to be calculated
101+
a, // pointer `a` containing 1st input vector of size n
102+
b, // pointer `b` containing 2nd input vector of size n
103+
y, // pointer `y` to the output vector of size n
104+
depends);
105+
}
106+
107+
using ew_cmn_ns::binary_contig_impl_fn_ptr_t;
108+
using ew_cmn_ns::binary_contig_matrix_contig_row_broadcast_impl_fn_ptr_t;
109+
using ew_cmn_ns::binary_contig_row_contig_matrix_broadcast_impl_fn_ptr_t;
110+
using ew_cmn_ns::binary_strided_impl_fn_ptr_t;
111+
112+
static int output_typeid_vector[td_ns::num_types][td_ns::num_types];
113+
static binary_contig_impl_fn_ptr_t contig_dispatch_vector[td_ns::num_types]
114+
[td_ns::num_types];
115+
116+
MACRO_POPULATE_DISPATCH_TABLES(copysign);
117+
} // namespace impl
118+
119+
void init_copysign(py::module_ m)
120+
{
121+
using arrayT = dpctl::tensor::usm_ndarray;
122+
using event_vecT = std::vector<sycl::event>;
123+
124+
impl::populate_dispatch_tables();
125+
using impl::contig_dispatch_vector;
126+
using impl::output_typeid_vector;
127+
128+
auto copysign_pyapi = [&](sycl::queue &exec_q, const arrayT &src1,
129+
const arrayT &src2, const arrayT &dst,
130+
const event_vecT &depends = {}) {
131+
return py_int::py_binary_ufunc(
132+
src1, src2, dst, exec_q, depends, output_typeid_vector,
133+
contig_dispatch_vector,
134+
// no support of strided implementation in OneMKL
135+
td_ns::NullPtrTable<impl::binary_strided_impl_fn_ptr_t>{},
136+
// no support of C-contig row with broadcasting in OneMKL
137+
td_ns::NullPtrTable<
138+
impl::
139+
binary_contig_matrix_contig_row_broadcast_impl_fn_ptr_t>{},
140+
td_ns::NullPtrTable<
141+
impl::
142+
binary_contig_row_contig_matrix_broadcast_impl_fn_ptr_t>{});
143+
};
144+
m.def(
145+
"_copysign", copysign_pyapi,
146+
"Call `copysign` function from OneMKL VM library to return `dst` of "
147+
"elements containing the next representable floating-point values "
148+
"following the values from the elements of `src1` in the direction of "
149+
"the corresponding elements of `src2`",
150+
py::arg("sycl_queue"), py::arg("src1"), py::arg("src2"), py::arg("dst"),
151+
py::arg("depends") = py::list());
152+
153+
auto copysign_need_to_call_pyapi = [&](sycl::queue &exec_q,
154+
const arrayT &src1,
155+
const arrayT &src2,
156+
const arrayT &dst) {
157+
return py_internal::need_to_call_binary_ufunc(exec_q, src1, src2, dst,
158+
output_typeid_vector,
159+
contig_dispatch_vector);
160+
};
161+
m.def("_mkl_copysign_to_call", copysign_need_to_call_pyapi,
162+
"Check input arguments to answer if `copysign` function from "
163+
"OneMKL VM library can be used",
164+
py::arg("sycl_queue"), py::arg("src1"), py::arg("src2"),
165+
py::arg("dst"));
166+
}
167+
} // namespace dpnp::extensions::vm
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
//*****************************************************************************
2+
// Copyright (c) 2025, 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::vm
33+
{
34+
void init_copysign(py::module_ m);
35+
} // namespace dpnp::extensions::vm

dpnp/backend/extensions/vm/vm_py.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include "cbrt.hpp"
4242
#include "ceil.hpp"
4343
#include "conj.hpp"
44+
#include "copysign.hpp"
4445
#include "cos.hpp"
4546
#include "cosh.hpp"
4647
#include "div.hpp"
@@ -90,6 +91,7 @@ PYBIND11_MODULE(_vm_impl, m)
9091
vm_ns::init_cbrt(m);
9192
vm_ns::init_ceil(m);
9293
vm_ns::init_conj(m);
94+
vm_ns::init_copysign(m);
9395
vm_ns::init_cos(m);
9496
vm_ns::init_cosh(m);
9597
vm_ns::init_div(m);

dpnp/dpnp_iface_mathematical.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -874,6 +874,8 @@ def clip(a, /, min=None, max=None, *, out=None, order="K", **kwargs):
874874
ti._copysign_result_type,
875875
ti._copysign,
876876
_COPYSIGN_DOCSTRING,
877+
mkl_fn_to_call="_mkl_copysign_to_call",
878+
mkl_impl_fn="_copysign",
877879
)
878880

879881

0 commit comments

Comments
 (0)