diff --git a/algorithms_cpp/include/embb/algorithms/internal/count-inl.h b/algorithms_cpp/include/embb/algorithms/internal/count-inl.h index f39672c..1a89751 100644 --- a/algorithms_cpp/include/embb/algorithms/internal/count-inl.h +++ b/algorithms_cpp/include/embb/algorithms/internal/count-inl.h @@ -37,42 +37,47 @@ namespace internal { template class ValueComparisonFunction{ public: - explicit ValueComparisonFunction(const ValueType &value) - :value_(value) {} - ValueComparisonFunction(const ValueComparisonFunction &other) - :value_(other.value_) {} + explicit ValueComparisonFunction(const ValueType& value) + : value_(value) {} + ValueComparisonFunction(const ValueComparisonFunction& other) + : value_(other.value_) {} template int operator()(ElementType element) { - if(element == value_) + if (element == value_) { return 1; - else + } + else { return 0; + } } private: const ValueType &value_; - ValueComparisonFunction &operator=(const ValueComparisonFunction &other); + ValueComparisonFunction &operator=( + const ValueComparisonFunction& other); }; template class FunctionComparisonFunction{ public: explicit FunctionComparisonFunction(Function function) - :function_(function) {} + : function_(function) {} FunctionComparisonFunction(const FunctionComparisonFunction &other) - :function_(other.function_) {} + : function_(other.function_) {} template int operator()(ElementType element) { - if(function_(element)) + if (function_(element)) { return 1; - else + } + else { return 0; + } } private: Function function_; - FunctionComparisonFunction &operator=(const FunctionComparisonFunction & - other); + FunctionComparisonFunction &operator=( + const FunctionComparisonFunction& other); }; } // namespace internal diff --git a/algorithms_cpp/include/embb/algorithms/internal/for_each-inl.h b/algorithms_cpp/include/embb/algorithms/internal/for_each-inl.h index d14dc87..6e7b634 100644 --- a/algorithms_cpp/include/embb/algorithms/internal/for_each-inl.h +++ b/algorithms_cpp/include/embb/algorithms/internal/for_each-inl.h @@ -77,15 +77,15 @@ class ForEachFunctor { mtapi::Task task_l = mtapi::Node::GetInstance().Spawn( mtapi::Action( base::MakeFunction( - functor_l, &ForEachFunctor::Action), + functor_l, &self_t::Action), policy_)); mtapi::Task task_r = mtapi::Node::GetInstance().Spawn( mtapi::Action( base::MakeFunction( - functor_r, &ForEachFunctor::Action), + functor_r, &self_t::Action), policy_)); - task_r.Wait(MTAPI_INFINITE); task_l.Wait(MTAPI_INFINITE); + task_r.Wait(MTAPI_INFINITE); } } @@ -118,7 +118,6 @@ void ForEachRecursive(RAI first, RAI last, Function unary, block_size = 1; } } - // Perform check of task number sufficiency if (((distance / block_size) * 2) + 1 > MTAPI_NODE_MAX_TASKS_DEFAULT) { EMBB_THROW(embb::base::ErrorException, "Not enough MTAPI tasks available " diff --git a/algorithms_cpp/include/embb/algorithms/internal/reduce-inl.h b/algorithms_cpp/include/embb/algorithms/internal/reduce-inl.h index 1aa8243..a687dcb 100644 --- a/algorithms_cpp/include/embb/algorithms/internal/reduce-inl.h +++ b/algorithms_cpp/include/embb/algorithms/internal/reduce-inl.h @@ -41,64 +41,75 @@ namespace internal { template class ReduceFunctor { + private: + typedef ReduceFunctor self_t; public: - ReduceFunctor(RAI first, RAI last, ReturnType neutral, + ReduceFunctor(size_t chunk_first, size_t chunk_last, + ReturnType neutral, ReductionFunction reduction, TransformationFunction transformation, - const embb::mtapi::ExecutionPolicy &policy, size_t block_size, + const embb::mtapi::ExecutionPolicy& policy, + const BlockSizePartitioner& partitioner, ReturnType& result) - : - first_(first), last_(last), neutral_(neutral), reduction_(reduction), - transformation_(transformation), policy_(policy), - block_size_(block_size), result_(result) { + : chunk_first_(chunk_first), chunk_last_(chunk_last), neutral_(neutral), + reduction_(reduction), transformation_(transformation), policy_(policy), + partitioner_(partitioner), result_(result) { } - void Action(mtapi::TaskContext& context) { - if (first_ == last_) { - return; - } - size_t distance = static_cast(std::distance(first_, last_)); - if (distance <= block_size_) { // leaf case -> do work + void Action(mtapi::TaskContext&) { + if (chunk_first_ == chunk_last_) { + // Leaf case, recursed to single chunk. Do work on chunk: + ChunkDescriptor chunk = partitioner_[chunk_first_]; + RAI first = chunk.GetFirst(); + RAI last = chunk.GetLast(); ReturnType result(neutral_); - for (RAI iter = first_; iter != last_; ++iter) { - result = reduction_(result, transformation_(*iter)); + for (RAI it = first; it != last; ++it) { + result = reduction_(result, transformation_(*it)); } result_ = result; - } else { // recurse further - internal::ChunkPartitioner partitioner(first_, last_, 2); - ChunkDescriptor chunk_l = partitioner[0]; - ChunkDescriptor chunk_r = partitioner[1]; + } + else { + // Recurse further: + size_t chunk_split_index = (chunk_first_ + chunk_last_) / 2; + // Split chunks into left / right branches: ReturnType result_l(neutral_); ReturnType result_r(neutral_); - ReduceFunctor functor_l(chunk_l.GetFirst(), - chunk_l.GetLast(), - neutral_, reduction_, transformation_, policy_, - block_size_, result_l); - ReduceFunctor functor_r(chunk_r.GetFirst(), - chunk_r.GetLast(), - neutral_, reduction_, transformation_, policy_, - block_size_, result_r); - // Spawn tasks for right partition first: + self_t functor_l(chunk_first_, + chunk_split_index, + neutral_, reduction_, transformation_, policy_, + partitioner_, + result_l); + self_t functor_r(chunk_split_index + 1, + chunk_last_, + neutral_, reduction_, transformation_, policy_, + partitioner_, + result_r); + mtapi::Task task_l = mtapi::Node::GetInstance().Spawn( + mtapi::Action( + base::MakeFunction( + functor_l, &self_t::Action), + policy_)); mtapi::Task task_r = mtapi::Node::GetInstance().Spawn( - mtapi::Action(base::MakeFunction( - functor_r, &ReduceFunctor::Action), + mtapi::Action( + base::MakeFunction( + functor_r, &self_t::Action), policy_)); - // Recurse on left partition: - functor_l.Action(context); - // Wait for tasks on right partition to complete: + task_l.Wait(MTAPI_INFINITE); task_r.Wait(MTAPI_INFINITE); result_ = reduction_(result_l, result_r); } } private: - RAI first_; - RAI last_; + size_t chunk_first_; + size_t chunk_last_; ReturnType neutral_; ReductionFunction reduction_; TransformationFunction transformation_; const embb::mtapi::ExecutionPolicy& policy_; - size_t block_size_; + const BlockSizePartitioner& partitioner_; ReturnType& result_; /** @@ -120,25 +131,34 @@ ReturnType ReduceRecursive(RAI first, RAI last, ReturnType neutral, if (distance == 0) { EMBB_THROW(embb::base::ErrorException, "Distance for Reduce is 0"); } - // Determine actually used block size mtapi::Node& node = mtapi::Node::GetInstance(); - size_t used_block_size = block_size; - if (used_block_size == 0) { - used_block_size = static_cast(distance) / node.GetCoreCount(); - if (used_block_size == 0) used_block_size = 1; + // Determine actually used block size + if (block_size == 0) { + block_size = (static_cast(distance) / node.GetCoreCount()); + if (block_size == 0) { + block_size = 1; + } } // Perform check of task number sufficiency - if (((distance / used_block_size) * 2) + 1 > MTAPI_NODE_MAX_TASKS_DEFAULT) { + if (((distance / block_size) * 2) + 1 > MTAPI_NODE_MAX_TASKS_DEFAULT) { EMBB_THROW(embb::base::ErrorException, "Number of computation tasks required in reduction would " "exceed MTAPI maximum number of tasks"); } - ReturnType result = neutral; + typedef ReduceFunctor Functor; - Functor functor(first, last, neutral, reduction, transformation, policy, - used_block_size, result); - mtapi::Task task = node.Spawn(mtapi::Action(base::MakeFunction( + BlockSizePartitioner partitioner(first, last, block_size); + ReturnType result = neutral; + Functor functor(0, + partitioner.Size() - 1, + neutral, + reduction, transformation, + policy, + partitioner, + result); + mtapi::Task task = node.Spawn( + mtapi::Action(base::MakeFunction( functor, &Functor::Action), policy)); task.Wait(MTAPI_INFINITE); return result;