Commit 81fd4c05 by Tobias Fuchs

algorithms_cpp: using block size partitioner in ForEach

parent 1ed7535d
......@@ -47,48 +47,54 @@ class ForEachFunctor {
/**
* Constructs a for-each functor with arguments.
*/
ForEachFunctor(RAI first, RAI last, Function unary,
const embb::mtapi::ExecutionPolicy& policy, size_t block_size)
: first_(first), last_(last), unary_(unary), policy_(policy),
block_size_(block_size) {
ForEachFunctor(size_t chunk_first, size_t chunk_last, Function unary,
const embb::mtapi::ExecutionPolicy& policy,
const BlockSizePartitioner<RAI>& partitioner)
: chunk_first_(chunk_first), chunk_last_(chunk_last),
unary_(unary), policy_(policy), partitioner_(partitioner) {
}
void Action(mtapi::TaskContext& context) {
size_t distance = static_cast<size_t>(std::distance(first_, last_));
if (distance == 0) return;
if (distance <= block_size_) { // leaf case -> do work
for (RAI it = first_; it != last_; ++it) {
void Action(mtapi::TaskContext&) {
if (chunk_first_ == chunk_last_) {
// Leaf case, recursed to single chunk. Do work on chunk:
ChunkDescriptor<RAI> chunk = partitioner_[chunk_first_];
RAI first = chunk.GetFirst();
RAI last = chunk.GetLast();
for (RAI it = first; it != last; ++it) {
unary_(*it);
}
} else { // recurse further
ChunkPartitioner<RAI> partitioner(first_, last_, 2);
ChunkDescriptor<RAI> chunk_l = partitioner[0];
ChunkDescriptor<RAI> 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:
}
else {
// Recurse further:
size_t chunk_split_index = (chunk_first_ + chunk_last_) / 2;
// Split chunks into left / right branches:
self_t functor_l(chunk_first_,
chunk_split_index,
unary_, policy_, partitioner_);
self_t functor_r(chunk_split_index + 1,
chunk_last_,
unary_, policy_, partitioner_);
mtapi::Task task_l = mtapi::Node::GetInstance().Spawn(
mtapi::Action(
base::MakeFunction(
functor_l, &ForEachFunctor<RAI, Function>::Action),
policy_));
mtapi::Task task_r = mtapi::Node::GetInstance().Spawn(
mtapi::Action(
base::MakeFunction(
functor_r, &ForEachFunctor<RAI, Function>::Action),
policy_));
// Recurse on left partition:
functor_l.Action(context);
// Wait for tasks on right partition to complete:
task_r.Wait(MTAPI_INFINITE);
task_l.Wait(MTAPI_INFINITE);
}
}
private:
RAI first_;
RAI last_;
size_t chunk_first_;
size_t chunk_last_;
Function unary_;
const embb::mtapi::ExecutionPolicy& policy_;
size_t block_size_;
const BlockSizePartitioner<RAI>& partitioner_;
/**
* Disables assignment.
......@@ -112,12 +118,17 @@ 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 "
"to perform the parallel foreach loop");
}
ForEachFunctor<RAI, Function> functor(first, last, unary, policy, block_size);
BlockSizePartitioner<RAI> partitioner(first, last, block_size);
ForEachFunctor<RAI, Function> functor(0,
partitioner.Size() - 1,
unary, policy, partitioner);
mtapi::Task task = node.Spawn(mtapi::Action(
base::MakeFunction(functor,
&ForEachFunctor<RAI, Function>::Action),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment