Skip to content

Rework implementation of dpnp.fmod function #1883

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

Merged
merged 40 commits into from
Jun 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
a8e2afb
Preparation to reuse common dpctl f/w for VM functions
antonwolfy Jun 4, 2024
a61d4e8
PoC to decouple abs implementation to separate source file
antonwolfy Jun 4, 2024
ed57483
Reuse typedef for function poiter from dpctl.tensor
antonwolfy Jun 4, 2024
71d745d
Define populating vectors by a separate macro
antonwolfy Jun 5, 2024
c2ea834
Move implementation of utility functions from headers to source to re…
antonwolfy Jun 5, 2024
7eb99d8
Separated implementation of acos function
antonwolfy Jun 5, 2024
2418e84
Separated implementation of acosh function
antonwolfy Jun 5, 2024
7748331
Use function to simplify strides from dpctl tensor headers
antonwolfy Jun 5, 2024
f9fbbce
PoC to decouple add implementation to separate source file
antonwolfy Jun 5, 2024
1d16fc3
Separated implementation of asin function
antonwolfy Jun 5, 2024
d2f31e5
Separated implementation of asinh function
antonwolfy Jun 5, 2024
d63fcff
Separated implementation of atan, atan2, atanh functions
antonwolfy Jun 5, 2024
ef195da
Resolve issue with calling MKL function for undefined types
antonwolfy Jun 6, 2024
a76d5e2
Separated implementation of cbrt, ceil, conj, cos and cosh functions
antonwolfy Jun 7, 2024
31b916f
Separated implementation of div, exp, exp2, expm1, floor and hypot fu…
antonwolfy Jun 7, 2024
616186e
Separated implementation of ln, log1p, log2 and log10 functions
antonwolfy Jun 7, 2024
3cd6f2d
Separated implementation of mul, pow, rint, sin and sinh functions
antonwolfy Jun 7, 2024
8c8b9aa
Separated implementation of sqr, sqrt, sub, tan, tanh and trunc funct…
antonwolfy Jun 10, 2024
fda9ec4
Removed unused header with types matrix
antonwolfy Jun 11, 2024
49ffe40
Remove unused functions
antonwolfy Jun 11, 2024
c565600
Use passing by reference in unary and binary funcs
antonwolfy Jun 12, 2024
b901b5b
Implement dpnp.fabs function
antonwolfy Jun 4, 2024
167fa47
Create an instance of DPNPUnaryFunc for fabs
antonwolfy Jun 12, 2024
18cdb60
Enable and add relating tests
antonwolfy Jun 12, 2024
a7f2a0c
Decouple populate logic to a macro
antonwolfy Jun 12, 2024
578d024
Resolve compilation failure on Win
antonwolfy Jun 12, 2024
59587fb
Merge branch 'master' into add-fabs-impl
antonwolfy Jun 12, 2024
9666e64
Implement dpnp.fmod function
antonwolfy Jun 13, 2024
7d5147b
Add vector implementation and dedicated kernel for boolean inputs
antonwolfy Jun 13, 2024
d8e190d
Update python implementation part
antonwolfy Jun 13, 2024
7eced0f
Add MKL function to the VM extension
antonwolfy Jun 14, 2024
f4c972b
Add tests
antonwolfy Jun 14, 2024
3f1b52c
Add a link to gh issue in arithmetic tests
antonwolfy Jun 14, 2024
c385569
Merge branch 'master' into add-fmod-impl
antonwolfy Jun 15, 2024
83b9c7d
Merge branch 'master' into add-fmod-impl
antonwolfy Jun 16, 2024
aa3fbf2
Suppress divide warning
antonwolfy Jun 17, 2024
2733489
Resolve compilation warning
antonwolfy Jun 17, 2024
62d8e0a
Updated docstring description of inputs per review comment
antonwolfy Jun 19, 2024
16b717d
Merge branch 'master' into add-fmod-impl
antonwolfy Jun 19, 2024
6a424b2
Merge branch 'master' into add-fmod-impl
antonwolfy Jun 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions dpnp/backend/extensions/ufunc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
set(_elementwise_sources
${CMAKE_CURRENT_SOURCE_DIR}/elementwise_functions/common.cpp
${CMAKE_CURRENT_SOURCE_DIR}/elementwise_functions/fabs.cpp
${CMAKE_CURRENT_SOURCE_DIR}/elementwise_functions/fmod.cpp
)

set(python_module_name _ufunc_impl)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <pybind11/pybind11.h>

#include "fabs.hpp"
#include "fmod.hpp"

namespace py = pybind11;

Expand All @@ -37,5 +38,6 @@ namespace dpnp::extensions::ufunc
void init_elementwise_functions(py::module_ m)
{
init_fabs(m);
init_fmod(m);
}
} // namespace dpnp::extensions::ufunc
193 changes: 193 additions & 0 deletions dpnp/backend/extensions/ufunc/elementwise_functions/fmod.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
//*****************************************************************************
// Copyright (c) 2024, 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.
//*****************************************************************************

#include <sycl/sycl.hpp>

#include "dpctl4pybind11.hpp"

#include "fmod.hpp"
#include "kernels/elementwise_functions/fmod.hpp"
#include "populate.hpp"

// include a local copy of elementwise common header from dpctl tensor:
// dpctl/tensor/libtensor/source/elementwise_functions/elementwise_functions.hpp
// TODO: replace by including dpctl header once available
#include "../../elementwise_functions/elementwise_functions.hpp"

// dpctl tensor headers
#include "kernels/elementwise_functions/common.hpp"
#include "utils/type_dispatch.hpp"

namespace py = pybind11;

namespace dpnp::extensions::ufunc
{
namespace ew_cmn_ns = dpctl::tensor::kernels::elementwise_common;
namespace py_int = dpnp::extensions::py_internal;
namespace td_ns = dpctl::tensor::type_dispatch;

using ew_cmn_ns::unary_contig_impl_fn_ptr_t;
using ew_cmn_ns::unary_strided_impl_fn_ptr_t;

namespace impl
{
/**
* @brief A factory to define pairs of supported types for which
* sycl::fmod<T> function is available.
*
* @tparam T1 Type of input vectors `a`
* @tparam T2 Type of input vectors `b`
*/
template <typename T1, typename T2>
struct OutputType
{
using value_type = typename std::disjunction<
td_ns::BinaryTypeMapResultEntry<T1, bool, T2, bool, std::int8_t>,
td_ns::BinaryTypeMapResultEntry<T1,
std::uint8_t,
T2,
std::uint8_t,
std::uint8_t>,
td_ns::BinaryTypeMapResultEntry<T1,
std::int8_t,
T2,
std::int8_t,
std::int8_t>,
td_ns::BinaryTypeMapResultEntry<T1,
std::uint16_t,
T2,
std::uint16_t,
std::uint16_t>,
td_ns::BinaryTypeMapResultEntry<T1,
std::int16_t,
T2,
std::int16_t,
std::int16_t>,
td_ns::BinaryTypeMapResultEntry<T1,
std::uint32_t,
T2,
std::uint32_t,
std::uint32_t>,
td_ns::BinaryTypeMapResultEntry<T1,
std::int32_t,
T2,
std::int32_t,
std::int32_t>,
td_ns::BinaryTypeMapResultEntry<T1,
std::uint64_t,
T2,
std::uint64_t,
std::uint64_t>,
td_ns::BinaryTypeMapResultEntry<T1,
std::int64_t,
T2,
std::int64_t,
std::int64_t>,
td_ns::BinaryTypeMapResultEntry<T1,
sycl::half,
T2,
sycl::half,
sycl::half>,
td_ns::BinaryTypeMapResultEntry<T1, float, T2, float, float>,
td_ns::BinaryTypeMapResultEntry<T1, double, T2, double, double>,
td_ns::DefaultResultEntry<void>>::result_type;
};

using dpnp::kernels::fmod::FmodFunctor;

template <typename argT1,
typename argT2,
typename resT,
unsigned int vec_sz = 4,
unsigned int n_vecs = 2,
bool enable_sg_loadstore = true>
using ContigFunctor =
ew_cmn_ns::BinaryContigFunctor<argT1,
argT2,
resT,
FmodFunctor<argT1, argT2, resT>,
vec_sz,
n_vecs,
enable_sg_loadstore>;

template <typename argT1, typename argT2, typename resT, typename IndexerT>
using StridedFunctor =
ew_cmn_ns::BinaryStridedFunctor<argT1,
argT2,
resT,
IndexerT,
FmodFunctor<argT1, argT2, resT>>;

using ew_cmn_ns::binary_contig_impl_fn_ptr_t;
using ew_cmn_ns::binary_contig_matrix_contig_row_broadcast_impl_fn_ptr_t;
using ew_cmn_ns::binary_contig_row_contig_matrix_broadcast_impl_fn_ptr_t;
using ew_cmn_ns::binary_strided_impl_fn_ptr_t;

static binary_contig_impl_fn_ptr_t fmod_contig_dispatch_table[td_ns::num_types]
[td_ns::num_types];
static int fmod_output_typeid_table[td_ns::num_types][td_ns::num_types];
static binary_strided_impl_fn_ptr_t
fmod_strided_dispatch_table[td_ns::num_types][td_ns::num_types];

MACRO_POPULATE_DISPATCH_TABLES(fmod);
} // namespace impl

void init_fmod(py::module_ m)
{
using arrayT = dpctl::tensor::usm_ndarray;
using event_vecT = std::vector<sycl::event>;
{
impl::populate_fmod_dispatch_tables();
using impl::fmod_contig_dispatch_table;
using impl::fmod_output_typeid_table;
using impl::fmod_strided_dispatch_table;

auto fmod_pyapi = [&](const arrayT &src1, const arrayT &src2,
const arrayT &dst, sycl::queue &exec_q,
const event_vecT &depends = {}) {
return py_int::py_binary_ufunc(
src1, src2, dst, exec_q, depends, fmod_output_typeid_table,
fmod_contig_dispatch_table, fmod_strided_dispatch_table,
// no support of C-contig row with broadcasting in OneMKL
td_ns::NullPtrTable<
impl::
binary_contig_matrix_contig_row_broadcast_impl_fn_ptr_t>{},
td_ns::NullPtrTable<
impl::
binary_contig_row_contig_matrix_broadcast_impl_fn_ptr_t>{});
};
m.def("_fmod", fmod_pyapi, "", py::arg("src1"), py::arg("src2"),
py::arg("dst"), py::arg("sycl_queue"),
py::arg("depends") = py::list());

auto fmod_result_type_pyapi = [&](const py::dtype &dtype1,
const py::dtype &dtype2) {
return py_int::py_binary_ufunc_result_type(
dtype1, dtype2, fmod_output_typeid_table);
};
m.def("_fmod_result_type", fmod_result_type_pyapi);
}
}
} // namespace dpnp::extensions::ufunc
35 changes: 35 additions & 0 deletions dpnp/backend/extensions/ufunc/elementwise_functions/fmod.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//*****************************************************************************
// Copyright (c) 2024, 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 <pybind11/pybind11.h>

namespace py = pybind11;

namespace dpnp::extensions::ufunc
{
void init_fmod(py::module_ m);
} // namespace dpnp::extensions::ufunc
110 changes: 109 additions & 1 deletion dpnp/backend/extensions/ufunc/elementwise_functions/populate.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
#pragma once

/**
* @brief A macro used to define factories and a populating universal functions.
* @brief A macro used to define factories and a populating unary universal
* functions.
*/
#define MACRO_POPULATE_DISPATCH_VECTORS(__name__) \
template <typename T1, typename T2, unsigned int vec_sz, \
Expand Down Expand Up @@ -120,3 +121,110 @@
dvb3; \
dvb3.populate_dispatch_vector(__name__##_output_typeid_vector); \
};

/**
* @brief A macro used to define factories and a populating binary universal
* functions.
*/
#define MACRO_POPULATE_DISPATCH_TABLES(__name__) \
template <typename argT1, typename argT2, typename resT, \
unsigned int vec_sz, unsigned int n_vecs> \
class __name__##_contig_kernel; \
\
template <typename argTy1, typename argTy2> \
sycl::event __name__##_contig_impl( \
sycl::queue &exec_q, size_t nelems, const char *arg1_p, \
py::ssize_t arg1_offset, const char *arg2_p, py::ssize_t arg2_offset, \
char *res_p, py::ssize_t res_offset, \
const std::vector<sycl::event> &depends = {}) \
{ \
return ew_cmn_ns::binary_contig_impl<argTy1, argTy2, OutputType, \
ContigFunctor, \
__name__##_contig_kernel>( \
exec_q, nelems, arg1_p, arg1_offset, arg2_p, arg2_offset, res_p, \
res_offset, depends); \
} \
\
template <typename fnT, typename T1, typename T2> \
struct ContigFactory \
{ \
fnT get() \
{ \
if constexpr (std::is_same_v< \
typename OutputType<T1, T2>::value_type, void>) \
{ \
\
fnT fn = nullptr; \
return fn; \
} \
else { \
fnT fn = __name__##_contig_impl<T1, T2>; \
return fn; \
} \
} \
}; \
\
template <typename fnT, typename T1, typename T2> \
struct TypeMapFactory \
{ \
std::enable_if_t<std::is_same<fnT, int>::value, int> get() \
{ \
using rT = typename OutputType<T1, T2>::value_type; \
return td_ns::GetTypeid<rT>{}.get(); \
} \
}; \
\
template <typename T1, typename T2, typename resT, typename IndexerT> \
class __name__##_strided_kernel; \
\
template <typename argTy1, typename argTy2> \
sycl::event __name__##_strided_impl( \
sycl::queue &exec_q, size_t nelems, int nd, \
const py::ssize_t *shape_and_strides, const char *arg1_p, \
py::ssize_t arg1_offset, const char *arg2_p, py::ssize_t arg2_offset, \
char *res_p, py::ssize_t res_offset, \
const std::vector<sycl::event> &depends, \
const std::vector<sycl::event> &additional_depends) \
{ \
return ew_cmn_ns::binary_strided_impl<argTy1, argTy2, OutputType, \
StridedFunctor, \
__name__##_strided_kernel>( \
exec_q, nelems, nd, shape_and_strides, arg1_p, arg1_offset, \
arg2_p, arg2_offset, res_p, res_offset, depends, \
additional_depends); \
} \
\
template <typename fnT, typename T1, typename T2> \
struct StridedFactory \
{ \
fnT get() \
{ \
if constexpr (std::is_same_v< \
typename OutputType<T1, T2>::value_type, void>) \
{ \
fnT fn = nullptr; \
return fn; \
} \
else { \
fnT fn = __name__##_strided_impl<T1, T2>; \
return fn; \
} \
} \
}; \
\
void populate_##__name__##_dispatch_tables(void) \
{ \
td_ns::DispatchTableBuilder<binary_contig_impl_fn_ptr_t, \
ContigFactory, td_ns::num_types> \
dvb1; \
dvb1.populate_dispatch_table(__name__##_contig_dispatch_table); \
\
td_ns::DispatchTableBuilder<binary_strided_impl_fn_ptr_t, \
StridedFactory, td_ns::num_types> \
dvb2; \
dvb2.populate_dispatch_table(__name__##_strided_dispatch_table); \
\
td_ns::DispatchTableBuilder<int, TypeMapFactory, td_ns::num_types> \
dvb3; \
dvb3.populate_dispatch_table(__name__##_output_typeid_table); \
};
1 change: 1 addition & 0 deletions dpnp/backend/extensions/vm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ set(_elementwise_sources
${CMAKE_CURRENT_SOURCE_DIR}/exp2.cpp
${CMAKE_CURRENT_SOURCE_DIR}/expm1.cpp
${CMAKE_CURRENT_SOURCE_DIR}/floor.cpp
${CMAKE_CURRENT_SOURCE_DIR}/fmod.cpp
${CMAKE_CURRENT_SOURCE_DIR}/hypot.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ln.cpp
${CMAKE_CURRENT_SOURCE_DIR}/log10.cpp
Expand Down
Loading
Loading