From 49cd15ea2f73b2a74b41c923d6b0e6e11a38757c Mon Sep 17 00:00:00 2001 From: Thomas Heller Date: Wed, 26 Oct 2016 15:41:37 +0200 Subject: [PATCH 1/2] Refining stable_partition - Improve exception handling - Make sure the "chunks == 1"-case is executed on the passed executor --- hpx/parallel/algorithms/partition.hpp | 171 ++++++++++++++++---------- 1 file changed, 104 insertions(+), 67 deletions(-) diff --git a/hpx/parallel/algorithms/partition.hpp b/hpx/parallel/algorithms/partition.hpp index e6487621afac..b4cc4be2b295 100644 --- a/hpx/parallel/algorithms/partition.hpp +++ b/hpx/parallel/algorithms/partition.hpp @@ -24,9 +24,12 @@ #include #include +#include + #include #include #include +#include #include #include @@ -40,59 +43,76 @@ namespace hpx { namespace parallel { HPX_INLINE_NAMESPACE(v1) struct stable_partition_helper { template - typename util::detail::algorithm_result::type + hpx::future operator()(ExPolicy && policy, RandIter first, RandIter last, - std::size_t size, F && f, Proj && proj, std::size_t chunks) + std::size_t size, F f, Proj proj, std::size_t chunks) { - typedef util::detail::algorithm_result result; - try { - if (chunks < 2) - { - return result::get(std::stable_partition( - first, last, - util::invoke_projected( - std::forward(f), std::forward(proj) - ))); - } + typedef typename hpx::util::decay::type::executor_type + executor_type; + typedef typename hpx::parallel::executor_traits + executor_traits; + if (chunks < 2) + { + return executor_traits::async_execute( + policy.executor(), + [first, last, f, proj]() -> RandIter + { + return std::stable_partition( + first, last, + util::invoke_projected(f, proj)); + }); + } - std::size_t mid_point = size / 2; - chunks /= 2; + std::size_t mid_point = size / 2; + chunks /= 2; - RandIter mid = first; - std::advance(mid, mid_point); + RandIter mid = first; + std::advance(mid, mid_point); - hpx::future left = hpx::async( - policy.executor(), *this, policy, first, mid, mid_point, - f, proj, chunks); - hpx::future right = hpx::async( - policy.executor(), *this, policy, mid, last, size - mid_point, - std::forward(f), std::forward(proj), chunks); + hpx::future left = executor_traits::async_execute( + policy.executor(), *this, policy, first, mid, mid_point, + f, proj, chunks); + hpx::future right = executor_traits::async_execute( + policy.executor(), *this, policy, mid, last, size - mid_point, + f, proj, chunks); - return result::get( - dataflow( - policy.executor(), - [mid]( - hpx::future && left, - hpx::future && right - ) -> RandIter + return + dataflow( + policy.executor(), + [mid]( + hpx::future && left, + hpx::future && right + ) -> RandIter + { + if (left.has_exception() || right.has_exception()) { - RandIter first = left.get(); - RandIter last = right.get(); + std::list errors; + if(left.has_exception()) + hpx::parallel::util::detail:: + handle_local_exceptions::call( + left.get_exception_ptr(), errors); + if(right.has_exception()) + hpx::parallel::util::detail:: + handle_local_exceptions::call( + right.get_exception_ptr(), errors); - std::rotate(first, mid, last); + if (!errors.empty()) + { + boost::throw_exception( + exception_list(std::move(errors))); + } + } + RandIter first = left.get(); + RandIter last = right.get(); - // for some library implementations std::rotate - // does not return the new middle point - std::advance(first, std::distance(mid, last)); - return first; - }, - std::move(left), std::move(right))); - } - catch (...) { - return result::get(detail::handle_exception< - ExPolicy, RandIter - >::call(boost::current_exception())); - } + std::rotate(first, mid, last); + + // for some library implementations std::rotate + // does not return the new middle point + std::advance(first, std::distance(mid, last)); + return first; + }, + std::move(left), std::move(right)); } }; @@ -124,37 +144,54 @@ namespace hpx { namespace parallel { HPX_INLINE_NAMESPACE(v1) parallel(ExPolicy && policy, RandIter first, RandIter last, F && f, Proj && proj) { + typedef util::detail::algorithm_result + algorithm_result; typedef typename std::iterator_traits::difference_type difference_type; - difference_type size = std::distance(first, last); + future result; - if (size == 0) - { - return util::detail::algorithm_result< - ExPolicy, RandIter - >::get(std::move(last)); - } + try { + difference_type size = std::distance(first, last); - typedef typename hpx::util::decay::type::executor_type - executor_type; - typedef typename - hpx::util::decay::type::executor_parameters_type - parameters_type; + if (size == 0) + { + result = hpx::make_ready_future(std::move(last)); + } + + typedef typename hpx::util::decay::type::executor_type + executor_type; + typedef typename + hpx::util::decay::type::executor_parameters_type + parameters_type; + + typedef executor_parameter_traits traits; + typedef executor_information_traits info_traits; - typedef executor_parameter_traits traits; - typedef executor_information_traits info_traits; + std::size_t const cores = + info_traits::processing_units_count(policy.executor(), + policy.parameters()); + std::size_t max_chunks = traits::maximal_number_of_chunks( + policy.parameters(), policy.executor(), cores, size); - std::size_t const cores = - info_traits::processing_units_count(policy.executor(), - policy.parameters()); - std::size_t max_chunks = traits::maximal_number_of_chunks( - policy.parameters(), policy.executor(), cores, size); + result = stable_partition_helper()( + std::forward(policy), first, last, size, + std::forward(f), std::forward(proj), + size == 1 ? 1 : (std::min)(std::size_t(size), max_chunks)); + } + catch (...) { + result = hpx::make_exceptional_future( + boost::current_exception()); + } + + if (result.has_exception()) + { + return algorithm_result::get( + detail::handle_exception::call( + std::move(result))); + } - return stable_partition_helper()( - std::forward(policy), first, last, size, - std::forward(f), std::forward(proj), - size == 1 ? 1 : (std::min)(std::size_t(size), max_chunks)); + return algorithm_result::get(std::move(result)); } }; /// \endcond From 2e727ad5f0db7c18cd4bab988d5b9ee6bcf3f277 Mon Sep 17 00:00:00 2001 From: Thomas Heller Date: Wed, 26 Oct 2016 15:42:48 +0200 Subject: [PATCH 2/2] Cleaning up exception_list - directly use hpx::exception copy constructur in assignment and cctor --- src/exception_list.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/exception_list.cpp b/src/exception_list.cpp index ebc88a86fd05..e5168a530ded 100644 --- a/src/exception_list.cpp +++ b/src/exception_list.cpp @@ -67,7 +67,7 @@ namespace hpx {} exception_list::exception_list(exception_list const& l) - : hpx::exception(l.size() ? hpx::get_error(l.exceptions_.front()) : success) + : hpx::exception(static_cast(l)) , exceptions_(l.exceptions_) {} @@ -80,8 +80,7 @@ namespace hpx { if (this != &l) { - *static_cast(this) = hpx::exception( - l.size() ? hpx::get_error(l.exceptions_.front()) : success); + *static_cast(this) = static_cast(l); exceptions_ = l.exceptions_; } return *this;