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 d8e9012..c1d0c6c 100644 --- a/algorithms_cpp/include/embb/algorithms/internal/for_each-inl.h +++ b/algorithms_cpp/include/embb/algorithms/internal/for_each-inl.h @@ -41,6 +41,8 @@ namespace internal { template class ForEachFunctor { + private: + typedef ForEachFunctor self_t; public: /** * Constructs a for-each functor with arguments. @@ -51,29 +53,33 @@ class ForEachFunctor { block_size_(block_size) { } - void Action(mtapi::TaskContext&) { + void Action(mtapi::TaskContext& context) { size_t distance = static_cast(std::distance(first_, last_)); if (distance == 0) return; if (distance <= block_size_) { // leaf case -> do work - for (RAI curIter(first_); curIter != last_; ++curIter) { - unary_(*curIter); + for (RAI it = first_; it != last_; ++it) { + unary_(*it); } } else { // recurse further ChunkPartitioner partitioner(first_, last_, 2); - ForEachFunctor functorL(partitioner[0].GetFirst(), - partitioner[0].GetLast(), unary_, policy_, block_size_); - ForEachFunctor functorR(partitioner[1].GetFirst(), - partitioner[1].GetLast(), unary_, policy_, block_size_); - - mtapi::Node& node = mtapi::Node::GetInstance(); - mtapi::Task taskL = node.Spawn(mtapi::Action(base::MakeFunction( - functorL, &ForEachFunctor::Action), + ChunkDescriptor chunk_l = partitioner[0]; + ChunkDescriptor chunk_r = partitioner[1]; + self_t functor_l(chunk_l.GetFirst(), + chunk_l.GetLast(), + unary_, policy_, block_size_); + self_t functor_r(chunk_r.GetFirst(), + chunk_r.GetLast(), + unary_, policy_, block_size_); + // Spawn tasks for right partition first: + mtapi::Task task_r = mtapi::Node::GetInstance().Spawn( + mtapi::Action( + base::MakeFunction( + functor_r, &ForEachFunctor::Action), policy_)); - mtapi::Task taskR = node.Spawn(mtapi::Action(base::MakeFunction( - functorR, &ForEachFunctor::Action), - policy_)); - taskL.Wait(MTAPI_INFINITE); - taskR.Wait(MTAPI_INFINITE); + // Recurse on left partition: + functor_l.Action(context); + // Wait for tasks on right partition to complete: + task_r.Wait(MTAPI_INFINITE); } } @@ -95,7 +101,9 @@ void ForEachRecursive(RAI first, RAI last, Function unary, const embb::mtapi::ExecutionPolicy& policy, size_t block_size) { typedef typename std::iterator_traits::difference_type difference_type; difference_type distance = std::distance(first, last); - assert(distance > 0); + if (distance == 0) { + EMBB_THROW(embb::base::ErrorException, "Distance for ForEach is 0"); + } mtapi::Node& node = mtapi::Node::GetInstance(); // Determine actually used block size if (block_size == 0) { @@ -127,7 +135,7 @@ void ForEachIteratorCheck(RAI first, RAI last, Function unary, } // namespace internal template -void ForEach(RAI first, RAI last, Function unary, +void ForEach(RAI first, const RAI last, Function unary, const embb::mtapi::ExecutionPolicy& policy, size_t block_size) { typename std::iterator_traits::iterator_category category; internal::ForEachIteratorCheck(first, last, unary, policy, block_size, diff --git a/algorithms_cpp/include/embb/algorithms/internal/partition-inl.h b/algorithms_cpp/include/embb/algorithms/internal/partition-inl.h index 996b162..cdb35bc 100644 --- a/algorithms_cpp/include/embb/algorithms/internal/partition-inl.h +++ b/algorithms_cpp/include/embb/algorithms/internal/partition-inl.h @@ -71,8 +71,8 @@ const ChunkDescriptor ForwardIterator last_new = first_new; - if (index == elements_count / chunkSize) { - std::advance(last_new, elements_count % chunkSize); + if (index >= chunks - 1) { + last_new = last; } else { std::advance(last_new, chunkSize); } diff --git a/algorithms_cpp/include/embb/algorithms/internal/reduce-inl.h b/algorithms_cpp/include/embb/algorithms/internal/reduce-inl.h index e03a235..1aa8243 100644 --- a/algorithms_cpp/include/embb/algorithms/internal/reduce-inl.h +++ b/algorithms_cpp/include/embb/algorithms/internal/reduce-inl.h @@ -53,7 +53,7 @@ class ReduceFunctor { block_size_(block_size), result_(result) { } - void Action(mtapi::TaskContext&) { + void Action(mtapi::TaskContext& context) { if (first_ == last_) { return; } @@ -66,22 +66,26 @@ class ReduceFunctor { result_ = result; } else { // recurse further internal::ChunkPartitioner partitioner(first_, last_, 2); + ChunkDescriptor chunk_l = partitioner[0]; + ChunkDescriptor chunk_r = partitioner[1]; ReturnType result_l(neutral_); ReturnType result_r(neutral_); - ReduceFunctor functor_l(partitioner[0].GetFirst(), - partitioner[0].GetLast(), + ReduceFunctor functor_l(chunk_l.GetFirst(), + chunk_l.GetLast(), neutral_, reduction_, transformation_, policy_, block_size_, result_l); - ReduceFunctor functor_r(partitioner[1].GetFirst(), - partitioner[1].GetLast(), + ReduceFunctor functor_r(chunk_r.GetFirst(), + chunk_r.GetLast(), neutral_, reduction_, transformation_, policy_, block_size_, result_r); - mtapi::Node& node = mtapi::Node::GetInstance(); - mtapi::Task task_l = node.Spawn(mtapi::Action(base::MakeFunction( - functor_l, &ReduceFunctor::Action), policy_)); - mtapi::Task task_r = node.Spawn(mtapi::Action(base::MakeFunction( - functor_r, &ReduceFunctor::Action), policy_)); - task_l.Wait(MTAPI_INFINITE); + // Spawn tasks for right partition first: + mtapi::Task task_r = mtapi::Node::GetInstance().Spawn( + mtapi::Action(base::MakeFunction( + functor_r, &ReduceFunctor::Action), + policy_)); + // Recurse on left partition: + functor_l.Action(context); + // Wait for tasks on right partition to complete: task_r.Wait(MTAPI_INFINITE); result_ = reduction_(result_l, result_r); } @@ -97,6 +101,9 @@ class ReduceFunctor { size_t block_size_; ReturnType& result_; + /** + * Disables assignment and copy-construction. + */ ReduceFunctor& operator=(const ReduceFunctor&); ReduceFunctor(const ReduceFunctor&); }; @@ -110,21 +117,22 @@ ReturnType ReduceRecursive(RAI first, RAI last, ReturnType neutral, size_t block_size) { typedef typename std::iterator_traits::difference_type difference_type; difference_type distance = std::distance(first, last); - assert(distance > 0); - + 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; } - + // Perform check of task number sufficiency if (((distance / used_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; diff --git a/algorithms_cpp/include/embb/algorithms/internal/scan-inl.h b/algorithms_cpp/include/embb/algorithms/internal/scan-inl.h index 6179431..d7eb2c6 100644 --- a/algorithms_cpp/include/embb/algorithms/internal/scan-inl.h +++ b/algorithms_cpp/include/embb/algorithms/internal/scan-inl.h @@ -54,7 +54,7 @@ class ScanFunctor { node_id_(node_id), parent_value_(neutral), is_first_pass_(going_down) { } - void Action(mtapi::TaskContext&) { + void Action(mtapi::TaskContext& context) { if (first_ == last_) { return; } @@ -67,23 +67,19 @@ class ScanFunctor { *iter_out = result; ++iter_in; ++iter_out; - while (iter_in != last_) { + for (; iter_in != last_; ++iter_in, ++iter_out) { result = scan_(result, transformation_(*iter_in)); *iter_out = result; - ++iter_in; - ++iter_out; } SetTreeValue(result); } else { // Second pass RAIIn iter_in = first_; RAIOut iter_out = output_iterator_; - while (iter_in != last_) { + for (; iter_in != last_; ++iter_in, ++iter_out) { *iter_out = scan_(parent_value_, *iter_out); - ++iter_in; - ++iter_out; } } - } else { + } else { // recurse further internal::ChunkPartitioner partitioner(first_, last_, 2); ScanFunctor functor_l(partitioner[0].GetFirst(), partitioner[0].GetLast(), output_iterator_, neutral_, scan_, transformation_, @@ -102,13 +98,13 @@ class ScanFunctor { functor_r.parent_value_ = functor_l.GetTreeValue() + parent_value_; } mtapi::Node& node = mtapi::Node::GetInstance(); - mtapi::Task task_l = node.Spawn(mtapi::Action(base::MakeFunction( - functor_l, &ScanFunctor::Action), + // Spawn tasks for right partition first: + mtapi::Task task_r = node.Spawn(mtapi::Action(base::MakeFunction( + functor_r, &ScanFunctor::Action), policy_)); - mtapi::Task task_r = node.Spawn(mtapi::Action(base::MakeFunction( - functor_r, &ScanFunctor::Action), - policy_)); - task_l.Wait(MTAPI_INFINITE); + // Recurse on left partition: + functor_l.Action(context); + // Wait for tasks on right partition to complete: task_r.Wait(MTAPI_INFINITE); SetTreeValue(scan_(functor_l.GetTreeValue(), functor_r.GetTreeValue())); }