From 58d18751779158e1b13d3166283912122eb398df Mon Sep 17 00:00:00 2001 From: Sergey Kopienko Date: Fri, 7 Jun 2024 10:54:54 +0200 Subject: [PATCH 1/4] include/oneapi/dpl/pstl/hetero/algorithm_impl_hetero.h - new predicates __find_if_unary_transform_op, __find_if_binary_reduce_op --- .../dpl/pstl/hetero/algorithm_impl_hetero.h | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/include/oneapi/dpl/pstl/hetero/algorithm_impl_hetero.h b/include/oneapi/dpl/pstl/hetero/algorithm_impl_hetero.h index 3bdc187ce7f..1d8e0075cf9 100644 --- a/include/oneapi/dpl/pstl/hetero/algorithm_impl_hetero.h +++ b/include/oneapi/dpl/pstl/hetero/algorithm_impl_hetero.h @@ -634,6 +634,37 @@ __pattern_count(__hetero_tag<_BackendTag>, _ExecutionPolicy&& __exec, _Iterator // any_of //------------------------------------------------------------------------ +template +struct __find_if_unary_transform_op +{ + _UnaryTransformOp __transform_op; + + template + _Tuple + operator()(const Arg& arg) const + { + return {__transform_op(std::get<0>(arg)), std::get<1>(arg)}; + } +}; + +template +struct __find_if_binary_reduce_op +{ + _Tuple + operator()(const _Tuple& op1, const _Tuple& op2) const + { + if (std::get<0>(op1) && std::get<0>(op2)) + { + if constexpr (_IsFirst{}) + return {true, std::min(std::get<1>(op1), std::get<1>(op2))}; + else + return {true, std::max(std::get<1>(op1), std::get<1>(op2))}; + } + + return std::get<0>(op1) ? op1 : op2; + } +}; + template bool __pattern_any_of(__hetero_tag<_BackendTag>, _ExecutionPolicy&& __exec, _Iterator __first, _Iterator __last, From 7497bf41aaab57b2de09fc66320d97ba9ad44653 Mon Sep 17 00:00:00 2001 From: Sergey Kopienko Date: Fri, 7 Jun 2024 10:55:47 +0200 Subject: [PATCH 2/4] include/oneapi/dpl/pstl/hetero/algorithm_impl_hetero.h - implementation of __pattern_any_of on __parallel_transform_reduce --- .../dpl/pstl/hetero/algorithm_impl_hetero.h | 43 +++++++++++++++---- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/include/oneapi/dpl/pstl/hetero/algorithm_impl_hetero.h b/include/oneapi/dpl/pstl/hetero/algorithm_impl_hetero.h index 1d8e0075cf9..0bea23faf1f 100644 --- a/include/oneapi/dpl/pstl/hetero/algorithm_impl_hetero.h +++ b/include/oneapi/dpl/pstl/hetero/algorithm_impl_hetero.h @@ -670,19 +670,44 @@ bool __pattern_any_of(__hetero_tag<_BackendTag>, _ExecutionPolicy&& __exec, _Iterator __first, _Iterator __last, _Pred __pred) { - if (__first == __last) + using _difference_type = typename ::std::iterator_traits<_Iterator>::difference_type; + + const _difference_type __n = __last - __first; + if (__n == 0) return false; - using _Predicate = oneapi::dpl::unseq_backend::single_match_pred<_ExecutionPolicy, _Pred>; + using _result_type = oneapi::dpl::__internal::tuple; + const auto __init = _result_type{false, __n}; - auto __keep = oneapi::dpl::__ranges::__get_sycl_range<__par_backend_hetero::access_mode::read, _Iterator>(); - auto __buf = __keep(__first, __last); + // __counting_iterator_t - iterate position (index) in source data + using __counting_iterator_t = oneapi::dpl::counting_iterator<_difference_type>; - return oneapi::dpl::__par_backend_hetero::__parallel_find_or( - _BackendTag{}, - __par_backend_hetero::make_wrapped_policy<__par_backend_hetero::__or_policy_wrapper>( - ::std::forward<_ExecutionPolicy>(__exec)), - _Predicate{__pred}, __par_backend_hetero::__parallel_or_tag{}, __buf.all_view()); + using _zipped_data_type = typename std::iterator_traits::value_type; + + __find_if_binary_reduce_op<_zipped_data_type, /*_IsFirst*/ std::true_type> __reduce_op; + __find_if_unary_transform_op<_zipped_data_type, _Pred> __transform_op{__pred}; + + using _Functor = unseq_backend::walk_n<_ExecutionPolicy, decltype(__transform_op)>; + using _RepackedTp = __par_backend_hetero::__repacked_tuple_t<_result_type>; + + auto __keep_src_data = + oneapi::dpl::__ranges::__get_sycl_range<__par_backend_hetero::access_mode::read, _Iterator>(); + auto __buf_src_data = __keep_src_data(__first, __last); + + const __counting_iterator_t __counting_it_first{0}, __counting_it_last{__n}; + auto __keep_counting_it = + oneapi::dpl::__ranges::__get_sycl_range<__par_backend_hetero::access_mode::read, __counting_iterator_t>(); + auto __buf_counting_it = __keep_counting_it(__counting_it_first, __counting_it_last); + + auto res = + oneapi::dpl::__par_backend_hetero::__parallel_transform_reduce<_RepackedTp, std::true_type /*is_commutative*/>( + _BackendTag{}, std::forward<_ExecutionPolicy>(__exec), __reduce_op, _Functor{__transform_op}, + unseq_backend::__init_value<_RepackedTp>{__init}, // initial value + oneapi::dpl::__ranges::make_zip_view(__buf_src_data.all_view(), __buf_counting_it.all_view())) + .get(); + + return std::get<0>(res); } //------------------------------------------------------------------------ From cd0b357e549dd80a9de80a33b4930f3ee8c059fb Mon Sep 17 00:00:00 2001 From: Sergey Kopienko Date: Fri, 7 Jun 2024 10:56:05 +0200 Subject: [PATCH 3/4] include/oneapi/dpl/pstl/hetero/algorithm_impl_hetero.h - implementation of __pattern_find_if on __parallel_transform_reduce --- .../dpl/pstl/hetero/algorithm_impl_hetero.h | 42 +++++++++++++++---- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/include/oneapi/dpl/pstl/hetero/algorithm_impl_hetero.h b/include/oneapi/dpl/pstl/hetero/algorithm_impl_hetero.h index 0bea23faf1f..8e99f3701e0 100644 --- a/include/oneapi/dpl/pstl/hetero/algorithm_impl_hetero.h +++ b/include/oneapi/dpl/pstl/hetero/algorithm_impl_hetero.h @@ -759,16 +759,44 @@ _Iterator __pattern_find_if(__hetero_tag<_BackendTag>, _ExecutionPolicy&& __exec, _Iterator __first, _Iterator __last, _Pred __pred) { - if (__first == __last) + using _difference_type = typename ::std::iterator_traits<_Iterator>::difference_type; + + const _difference_type __n = __last - __first; + if (__n == 0) return __last; - using _Predicate = oneapi::dpl::unseq_backend::single_match_pred<_ExecutionPolicy, _Pred>; + using _result_type = oneapi::dpl::__internal::tuple; + const auto __init = _result_type{false, __n}; - return __par_backend_hetero::__parallel_find( - _BackendTag{}, ::std::forward<_ExecutionPolicy>(__exec), - __par_backend_hetero::make_iter_mode<__par_backend_hetero::access_mode::read>(__first), - __par_backend_hetero::make_iter_mode<__par_backend_hetero::access_mode::read>(__last), _Predicate{__pred}, - ::std::true_type{}); + // __counting_iterator_t - iterate position (index) in source data + using __counting_iterator_t = oneapi::dpl::counting_iterator<_difference_type>; + + using _zipped_data_type = typename std::iterator_traits::value_type; + + __find_if_binary_reduce_op<_zipped_data_type, /*_IsFirst*/ std::true_type> __reduce_op; + __find_if_unary_transform_op<_zipped_data_type, _Pred> __transform_op{__pred}; + + using _Functor = unseq_backend::walk_n<_ExecutionPolicy, decltype(__transform_op)>; + using _RepackedTp = __par_backend_hetero::__repacked_tuple_t<_result_type>; + + auto __keep_src_data = + oneapi::dpl::__ranges::__get_sycl_range<__par_backend_hetero::access_mode::read, _Iterator>(); + auto __buf_src_data = __keep_src_data(__first, __last); + + const __counting_iterator_t __counting_it_first{0}, __counting_it_last{__n}; + auto __keep_counting_it = + oneapi::dpl::__ranges::__get_sycl_range<__par_backend_hetero::access_mode::read, __counting_iterator_t>(); + auto __buf_counting_it = __keep_counting_it(__counting_it_first, __counting_it_last); + + auto res = + oneapi::dpl::__par_backend_hetero::__parallel_transform_reduce<_RepackedTp, std::true_type /*is_commutative*/>( + _BackendTag{}, std::forward<_ExecutionPolicy>(__exec), __reduce_op, _Functor{__transform_op}, + unseq_backend::__init_value<_RepackedTp>{__init}, // initial value + oneapi::dpl::__ranges::make_zip_view(__buf_src_data.all_view(), __buf_counting_it.all_view())) + .get(); + + return std::get<0>(res) ? __first + std::get<1>(res) : __last; } //------------------------------------------------------------------------ From f6d73e1d484a8dac2f66b40bad7bc1325b97c828 Mon Sep 17 00:00:00 2001 From: Sergey Kopienko Date: Thu, 13 Jun 2024 11:40:10 +0200 Subject: [PATCH 4/4] include/oneapi/dpl/pstl/hetero/algorithm_impl_hetero.h - implementation of __pattern_any_of on __parallel_transform_reduce - fix review comment: counting iterator not required. Signed-off-by: Sergey Kopienko --- .../dpl/pstl/hetero/algorithm_impl_hetero.h | 94 +++++++++---------- 1 file changed, 45 insertions(+), 49 deletions(-) diff --git a/include/oneapi/dpl/pstl/hetero/algorithm_impl_hetero.h b/include/oneapi/dpl/pstl/hetero/algorithm_impl_hetero.h index 8e99f3701e0..56b6a28d45d 100644 --- a/include/oneapi/dpl/pstl/hetero/algorithm_impl_hetero.h +++ b/include/oneapi/dpl/pstl/hetero/algorithm_impl_hetero.h @@ -634,34 +634,12 @@ __pattern_count(__hetero_tag<_BackendTag>, _ExecutionPolicy&& __exec, _Iterator // any_of //------------------------------------------------------------------------ -template -struct __find_if_unary_transform_op +struct __any_of_binary_reduce_op { - _UnaryTransformOp __transform_op; - - template - _Tuple - operator()(const Arg& arg) const + bool + operator()(bool op1, bool op2) const { - return {__transform_op(std::get<0>(arg)), std::get<1>(arg)}; - } -}; - -template -struct __find_if_binary_reduce_op -{ - _Tuple - operator()(const _Tuple& op1, const _Tuple& op2) const - { - if (std::get<0>(op1) && std::get<0>(op2)) - { - if constexpr (_IsFirst{}) - return {true, std::min(std::get<1>(op1), std::get<1>(op2))}; - else - return {true, std::max(std::get<1>(op1), std::get<1>(op2))}; - } - - return std::get<0>(op1) ? op1 : op2; + return op1 || op2; } }; @@ -676,38 +654,25 @@ __pattern_any_of(__hetero_tag<_BackendTag>, _ExecutionPolicy&& __exec, _Iterator if (__n == 0) return false; - using _result_type = oneapi::dpl::__internal::tuple; - const auto __init = _result_type{false, __n}; - - // __counting_iterator_t - iterate position (index) in source data - using __counting_iterator_t = oneapi::dpl::counting_iterator<_difference_type>; + using _data_type = typename ::std::iterator_traits<_Iterator>::value_type; - using _zipped_data_type = typename std::iterator_traits::value_type; + using _result_type = oneapi::dpl::__internal::tuple; + const bool __init = false; - __find_if_binary_reduce_op<_zipped_data_type, /*_IsFirst*/ std::true_type> __reduce_op; - __find_if_unary_transform_op<_zipped_data_type, _Pred> __transform_op{__pred}; + __any_of_binary_reduce_op __reduce_op; - using _Functor = unseq_backend::walk_n<_ExecutionPolicy, decltype(__transform_op)>; + using _Functor = unseq_backend::walk_n<_ExecutionPolicy, decltype(__pred)>; using _RepackedTp = __par_backend_hetero::__repacked_tuple_t<_result_type>; auto __keep_src_data = oneapi::dpl::__ranges::__get_sycl_range<__par_backend_hetero::access_mode::read, _Iterator>(); auto __buf_src_data = __keep_src_data(__first, __last); - const __counting_iterator_t __counting_it_first{0}, __counting_it_last{__n}; - auto __keep_counting_it = - oneapi::dpl::__ranges::__get_sycl_range<__par_backend_hetero::access_mode::read, __counting_iterator_t>(); - auto __buf_counting_it = __keep_counting_it(__counting_it_first, __counting_it_last); - - auto res = - oneapi::dpl::__par_backend_hetero::__parallel_transform_reduce<_RepackedTp, std::true_type /*is_commutative*/>( - _BackendTag{}, std::forward<_ExecutionPolicy>(__exec), __reduce_op, _Functor{__transform_op}, - unseq_backend::__init_value<_RepackedTp>{__init}, // initial value - oneapi::dpl::__ranges::make_zip_view(__buf_src_data.all_view(), __buf_counting_it.all_view())) - .get(); - - return std::get<0>(res); + return oneapi::dpl::__par_backend_hetero::__parallel_transform_reduce( + _BackendTag{}, std::forward<_ExecutionPolicy>(__exec), __reduce_op, _Functor{__pred}, + unseq_backend::__init_value{__init}, // initial value + __buf_src_data.all_view()) + .get(); } //------------------------------------------------------------------------ @@ -754,6 +719,37 @@ __pattern_equal(__hetero_tag<_BackendTag> __tag, _ExecutionPolicy&& __exec, _Ite // find_if //------------------------------------------------------------------------ +template +struct __find_if_unary_transform_op +{ + _UnaryTransformOp __transform_op; + + template + _Tuple + operator()(const Arg& arg) const + { + return {__transform_op(std::get<0>(arg)), std::get<1>(arg)}; + } +}; + +template +struct __find_if_binary_reduce_op +{ + _Tuple + operator()(const _Tuple& op1, const _Tuple& op2) const + { + if (std::get<0>(op1) && std::get<0>(op2)) + { + if constexpr (_IsFirst{}) + return {true, std::min(std::get<1>(op1), std::get<1>(op2))}; + else + return {true, std::max(std::get<1>(op1), std::get<1>(op2))}; + } + + return std::get<0>(op1) ? op1 : op2; + } +}; + template _Iterator __pattern_find_if(__hetero_tag<_BackendTag>, _ExecutionPolicy&& __exec, _Iterator __first, _Iterator __last,