diff --git a/dpnp/backend/extensions/vm/add.hpp b/dpnp/backend/extensions/vm/add.hpp new file mode 100644 index 000000000000..d80755f0ec0b --- /dev/null +++ b/dpnp/backend/extensions/vm/add.hpp @@ -0,0 +1,81 @@ +//***************************************************************************** +// Copyright (c) 2023, Intel Corporation +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +// THE POSSIBILITY OF SUCH DAMAGE. +//***************************************************************************** + +#pragma once + +#include + +#include "common.hpp" +#include "types_matrix.hpp" + +namespace dpnp +{ +namespace backend +{ +namespace ext +{ +namespace vm +{ +template +sycl::event add_contig_impl(sycl::queue exec_q, + const std::int64_t n, + const char *in_a, + const char *in_b, + char *out_y, + const std::vector &depends) +{ + type_utils::validate_type_for_device(exec_q); + + const T *a = reinterpret_cast(in_a); + const T *b = reinterpret_cast(in_b); + T *y = reinterpret_cast(out_y); + + return mkl_vm::add(exec_q, + n, // number of elements to be calculated + a, // pointer `a` containing 1st input vector of size n + b, // pointer `b` containing 2nd input vector of size n + y, // pointer `y` to the output vector of size n + depends); +} + +template +struct AddContigFactory +{ + fnT get() + { + if constexpr (std::is_same_v< + typename types::AddOutputType::value_type, void>) + { + return nullptr; + } + else { + return add_contig_impl; + } + } +}; +} // namespace vm +} // namespace ext +} // namespace backend +} // namespace dpnp diff --git a/dpnp/backend/extensions/vm/mul.hpp b/dpnp/backend/extensions/vm/mul.hpp new file mode 100644 index 000000000000..4f827a056192 --- /dev/null +++ b/dpnp/backend/extensions/vm/mul.hpp @@ -0,0 +1,81 @@ +//***************************************************************************** +// Copyright (c) 2023, Intel Corporation +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +// THE POSSIBILITY OF SUCH DAMAGE. +//***************************************************************************** + +#pragma once + +#include + +#include "common.hpp" +#include "types_matrix.hpp" + +namespace dpnp +{ +namespace backend +{ +namespace ext +{ +namespace vm +{ +template +sycl::event mul_contig_impl(sycl::queue exec_q, + const std::int64_t n, + const char *in_a, + const char *in_b, + char *out_y, + const std::vector &depends) +{ + type_utils::validate_type_for_device(exec_q); + + const T *a = reinterpret_cast(in_a); + const T *b = reinterpret_cast(in_b); + T *y = reinterpret_cast(out_y); + + return mkl_vm::mul(exec_q, + n, // number of elements to be calculated + a, // pointer `a` containing 1st input vector of size n + b, // pointer `b` containing 2nd input vector of size n + y, // pointer `y` to the output vector of size n + depends); +} + +template +struct MulContigFactory +{ + fnT get() + { + if constexpr (std::is_same_v< + typename types::MulOutputType::value_type, void>) + { + return nullptr; + } + else { + return mul_contig_impl; + } + } +}; +} // namespace vm +} // namespace ext +} // namespace backend +} // namespace dpnp diff --git a/dpnp/backend/extensions/vm/sub.hpp b/dpnp/backend/extensions/vm/sub.hpp new file mode 100644 index 000000000000..f7bec14d48bf --- /dev/null +++ b/dpnp/backend/extensions/vm/sub.hpp @@ -0,0 +1,81 @@ +//***************************************************************************** +// Copyright (c) 2023, Intel Corporation +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +// THE POSSIBILITY OF SUCH DAMAGE. +//***************************************************************************** + +#pragma once + +#include + +#include "common.hpp" +#include "types_matrix.hpp" + +namespace dpnp +{ +namespace backend +{ +namespace ext +{ +namespace vm +{ +template +sycl::event sub_contig_impl(sycl::queue exec_q, + const std::int64_t n, + const char *in_a, + const char *in_b, + char *out_y, + const std::vector &depends) +{ + type_utils::validate_type_for_device(exec_q); + + const T *a = reinterpret_cast(in_a); + const T *b = reinterpret_cast(in_b); + T *y = reinterpret_cast(out_y); + + return mkl_vm::sub(exec_q, + n, // number of elements to be calculated + a, // pointer `a` containing 1st input vector of size n + b, // pointer `b` containing 2nd input vector of size n + y, // pointer `y` to the output vector of size n + depends); +} + +template +struct SubContigFactory +{ + fnT get() + { + if constexpr (std::is_same_v< + typename types::SubOutputType::value_type, void>) + { + return nullptr; + } + else { + return sub_contig_impl; + } + } +}; +} // namespace vm +} // namespace ext +} // namespace backend +} // namespace dpnp diff --git a/dpnp/backend/extensions/vm/types_matrix.hpp b/dpnp/backend/extensions/vm/types_matrix.hpp index cd4fd76d4bef..ba88f192908d 100644 --- a/dpnp/backend/extensions/vm/types_matrix.hpp +++ b/dpnp/backend/extensions/vm/types_matrix.hpp @@ -45,12 +45,12 @@ namespace types { /** * @brief A factory to define pairs of supported types for which - * MKL VM library provides support in oneapi::mkl::vm::div function. + * MKL VM library provides support in oneapi::mkl::vm::add function. * * @tparam T Type of input vectors `a` and `b` and of result vector `y`. */ template -struct DivOutputType +struct AddOutputType { using value_type = typename std::disjunction< dpctl_td_ns::BinaryTypeMapResultEntry>::result_type; }; +/** + * @brief A factory to define pairs of supported types for which + * MKL VM library provides support in oneapi::mkl::vm::div function. + * + * @tparam T Type of input vectors `a` and `b` and of result vector `y`. + */ +template +struct DivOutputType +{ + using value_type = typename std::disjunction< + dpctl_td_ns::BinaryTypeMapResultEntry, + T, + std::complex, + std::complex>, + dpctl_td_ns::BinaryTypeMapResultEntry, + T, + std::complex, + std::complex>, + dpctl_td_ns::BinaryTypeMapResultEntry, + dpctl_td_ns::BinaryTypeMapResultEntry, + dpctl_td_ns::DefaultResultEntry>::result_type; +}; + /** * @brief A factory to define pairs of supported types for which * MKL VM library provides support in oneapi::mkl::vm::floor function. @@ -136,6 +161,31 @@ struct LnOutputType dpctl_td_ns::DefaultResultEntry>::result_type; }; +/** + * @brief A factory to define pairs of supported types for which + * MKL VM library provides support in oneapi::mkl::vm::mul function. + * + * @tparam T Type of input vectors `a` and `b` and of result vector `y`. + */ +template +struct MulOutputType +{ + using value_type = typename std::disjunction< + dpctl_td_ns::BinaryTypeMapResultEntry, + T, + std::complex, + std::complex>, + dpctl_td_ns::BinaryTypeMapResultEntry, + T, + std::complex, + std::complex>, + dpctl_td_ns::BinaryTypeMapResultEntry, + dpctl_td_ns::BinaryTypeMapResultEntry, + dpctl_td_ns::DefaultResultEntry>::result_type; +}; + /** * @brief A factory to define pairs of supported types for which * MKL VM library provides support in oneapi::mkl::vm::sin function. @@ -189,6 +239,31 @@ struct SqrtOutputType dpctl_td_ns::DefaultResultEntry>::result_type; }; +/** + * @brief A factory to define pairs of supported types for which + * MKL VM library provides support in oneapi::mkl::vm::sub function. + * + * @tparam T Type of input vectors `a` and `b` and of result vector `y`. + */ +template +struct SubOutputType +{ + using value_type = typename std::disjunction< + dpctl_td_ns::BinaryTypeMapResultEntry, + T, + std::complex, + std::complex>, + dpctl_td_ns::BinaryTypeMapResultEntry, + T, + std::complex, + std::complex>, + dpctl_td_ns::BinaryTypeMapResultEntry, + dpctl_td_ns::BinaryTypeMapResultEntry, + dpctl_td_ns::DefaultResultEntry>::result_type; +}; + /** * @brief A factory to define pairs of supported types for which * MKL VM library provides support in oneapi::mkl::vm::trunc function. diff --git a/dpnp/backend/extensions/vm/vm_py.cpp b/dpnp/backend/extensions/vm/vm_py.cpp index c7435ae9e2eb..e4f470bee3ce 100644 --- a/dpnp/backend/extensions/vm/vm_py.cpp +++ b/dpnp/backend/extensions/vm/vm_py.cpp @@ -30,15 +30,18 @@ #include #include +#include "add.hpp" #include "ceil.hpp" #include "common.hpp" #include "cos.hpp" #include "div.hpp" #include "floor.hpp" #include "ln.hpp" +#include "mul.hpp" #include "sin.hpp" #include "sqr.hpp" #include "sqrt.hpp" +#include "sub.hpp" #include "trunc.hpp" #include "types_matrix.hpp" @@ -48,15 +51,17 @@ namespace vm_ext = dpnp::backend::ext::vm; using vm_ext::binary_impl_fn_ptr_t; using vm_ext::unary_impl_fn_ptr_t; -static binary_impl_fn_ptr_t div_dispatch_vector[dpctl_td_ns::num_types]; - +static binary_impl_fn_ptr_t add_dispatch_vector[dpctl_td_ns::num_types]; static unary_impl_fn_ptr_t ceil_dispatch_vector[dpctl_td_ns::num_types]; static unary_impl_fn_ptr_t cos_dispatch_vector[dpctl_td_ns::num_types]; +static binary_impl_fn_ptr_t div_dispatch_vector[dpctl_td_ns::num_types]; static unary_impl_fn_ptr_t floor_dispatch_vector[dpctl_td_ns::num_types]; static unary_impl_fn_ptr_t ln_dispatch_vector[dpctl_td_ns::num_types]; +static binary_impl_fn_ptr_t mul_dispatch_vector[dpctl_td_ns::num_types]; static unary_impl_fn_ptr_t sin_dispatch_vector[dpctl_td_ns::num_types]; static unary_impl_fn_ptr_t sqr_dispatch_vector[dpctl_td_ns::num_types]; static unary_impl_fn_ptr_t sqrt_dispatch_vector[dpctl_td_ns::num_types]; +static binary_impl_fn_ptr_t sub_dispatch_vector[dpctl_td_ns::num_types]; static unary_impl_fn_ptr_t trunc_dispatch_vector[dpctl_td_ns::num_types]; PYBIND11_MODULE(_vm_impl, m) @@ -64,31 +69,31 @@ PYBIND11_MODULE(_vm_impl, m) using arrayT = dpctl::tensor::usm_ndarray; using event_vecT = std::vector; - // BinaryUfunc: ==== Div(x1, x2) ==== + // BinaryUfunc: ==== Add(x1, x2) ==== { vm_ext::init_ufunc_dispatch_vector( - div_dispatch_vector); + vm_ext::AddContigFactory>( + add_dispatch_vector); - auto div_pyapi = [&](sycl::queue exec_q, arrayT src1, arrayT src2, + auto add_pyapi = [&](sycl::queue exec_q, arrayT src1, arrayT src2, arrayT dst, const event_vecT &depends = {}) { return vm_ext::binary_ufunc(exec_q, src1, src2, dst, depends, - div_dispatch_vector); + add_dispatch_vector); }; - m.def("_div", div_pyapi, - "Call `div` function from OneMKL VM library to performs element " - "by element division of vector `src1` by vector `src2` " + m.def("_add", add_pyapi, + "Call `add` function from OneMKL VM library to performs element " + "by element addition of vector `src1` by vector `src2` " "to resulting vector `dst`", py::arg("sycl_queue"), py::arg("src1"), py::arg("src2"), py::arg("dst"), py::arg("depends") = py::list()); - auto div_need_to_call_pyapi = [&](sycl::queue exec_q, arrayT src1, + auto add_need_to_call_pyapi = [&](sycl::queue exec_q, arrayT src1, arrayT src2, arrayT dst) { return vm_ext::need_to_call_binary_ufunc(exec_q, src1, src2, dst, - div_dispatch_vector); + add_dispatch_vector); }; - m.def("_mkl_div_to_call", div_need_to_call_pyapi, - "Check input arguments to answer if `div` function from " + m.def("_mkl_add_to_call", add_need_to_call_pyapi, + "Check input arguments to answer if `add` function from " "OneMKL VM library can be used", py::arg("sycl_queue"), py::arg("src1"), py::arg("src2"), py::arg("dst")); @@ -150,6 +155,36 @@ PYBIND11_MODULE(_vm_impl, m) py::arg("sycl_queue"), py::arg("src"), py::arg("dst")); } + // BinaryUfunc: ==== Div(x1, x2) ==== + { + vm_ext::init_ufunc_dispatch_vector( + div_dispatch_vector); + + auto div_pyapi = [&](sycl::queue exec_q, arrayT src1, arrayT src2, + arrayT dst, const event_vecT &depends = {}) { + return vm_ext::binary_ufunc(exec_q, src1, src2, dst, depends, + div_dispatch_vector); + }; + m.def("_div", div_pyapi, + "Call `div` function from OneMKL VM library to performs element " + "by element division of vector `src1` by vector `src2` " + "to resulting vector `dst`", + py::arg("sycl_queue"), py::arg("src1"), py::arg("src2"), + py::arg("dst"), py::arg("depends") = py::list()); + + auto div_need_to_call_pyapi = [&](sycl::queue exec_q, arrayT src1, + arrayT src2, arrayT dst) { + return vm_ext::need_to_call_binary_ufunc(exec_q, src1, src2, dst, + div_dispatch_vector); + }; + m.def("_mkl_div_to_call", div_need_to_call_pyapi, + "Check input arguments to answer if `div` function from " + "OneMKL VM library can be used", + py::arg("sycl_queue"), py::arg("src1"), py::arg("src2"), + py::arg("dst")); + } + // UnaryUfunc: ==== Floor(x) ==== { vm_ext::init_ufunc_dispatch_vector( + mul_dispatch_vector); + + auto mul_pyapi = [&](sycl::queue exec_q, arrayT src1, arrayT src2, + arrayT dst, const event_vecT &depends = {}) { + return vm_ext::binary_ufunc(exec_q, src1, src2, dst, depends, + mul_dispatch_vector); + }; + m.def("_mul", mul_pyapi, + "Call `mul` function from OneMKL VM library to performs element " + "by element multiplication of vector `src1` by vector `src2` " + "to resulting vector `dst`", + py::arg("sycl_queue"), py::arg("src1"), py::arg("src2"), + py::arg("dst"), py::arg("depends") = py::list()); + + auto mul_need_to_call_pyapi = [&](sycl::queue exec_q, arrayT src1, + arrayT src2, arrayT dst) { + return vm_ext::need_to_call_binary_ufunc(exec_q, src1, src2, dst, + mul_dispatch_vector); + }; + m.def("_mkl_mul_to_call", mul_need_to_call_pyapi, + "Check input arguments to answer if `mul` function from " + "OneMKL VM library can be used", + py::arg("sycl_queue"), py::arg("src1"), py::arg("src2"), + py::arg("dst")); + } + // UnaryUfunc: ==== Sin(x) ==== { vm_ext::init_ufunc_dispatch_vector( + sub_dispatch_vector); + + auto sub_pyapi = [&](sycl::queue exec_q, arrayT src1, arrayT src2, + arrayT dst, const event_vecT &depends = {}) { + return vm_ext::binary_ufunc(exec_q, src1, src2, dst, depends, + sub_dispatch_vector); + }; + m.def("_sub", sub_pyapi, + "Call `sub` function from OneMKL VM library to performs element " + "by element subtraction of vector `src1` by vector `src2` " + "to resulting vector `dst`", + py::arg("sycl_queue"), py::arg("src1"), py::arg("src2"), + py::arg("dst"), py::arg("depends") = py::list()); + + auto sub_need_to_call_pyapi = [&](sycl::queue exec_q, arrayT src1, + arrayT src2, arrayT dst) { + return vm_ext::need_to_call_binary_ufunc(exec_q, src1, src2, dst, + sub_dispatch_vector); + }; + m.def("_mkl_sub_to_call", sub_need_to_call_pyapi, + "Check input arguments to answer if `sub` function from " + "OneMKL VM library can be used", + py::arg("sycl_queue"), py::arg("src1"), py::arg("src2"), + py::arg("dst")); + } + // UnaryUfunc: ==== Trunc(x) ==== { vm_ext::init_ufunc_dispatch_vector