HPX - High Performance ParalleX

PrevUpHomeNext

Using Task Regions

The task_region, run and the wait functions implemented based on N4088 are based on the task_group concept that is a part of the common subset of the Microsoft Parallel Patterns Library (PPL) and the Intel Threading Building Blocks (TBB) libraries.

This implementations adopts a simpler syntax than exposed by those libraries - one that is influenced by language-based concepts such as spawn and sync from Cilk++ and async and finish from X10. It improves on existing practice in the following ways:

Consider an example of a parallel traversal of a tree, where a user-provided function compute is applied to each node of the tree, returning the sum of the results:

template <typename Func>
int traverse(node& n, Func && compute)
{
    int left = 0, right = 0;
    task_region(
        [&](task_region_handle& tr) {
            if (n.left)
                tr.run([&] { left = traverse(*n.left, compute); });
            if (n.right)
                tr.run([&] { right = traverse(*n.right, compute); });
        });

    return compute(n) + left + right;
}

The example above demonstrates the use of two of the functions, task_region and the run member function of a task_region_handle.

The task_region function delineates a region in a program code potentially containing invocations of threads spawned by the run member function of the task_region_handle class. The run function spawns an HPX thread, a unit of work that is allowed to execute in parallel with respect to the caller. Any parallel tasks spawned by run within the task_region are joined back to a single thread of execution at the end of the task_region. run takes a user-provided function object f and starts it asynchronously - i.e. it may return before the execution of f completes. The HPX scheduler may choose to run f immediately or delay running f until compute resources become available.

A task_region_handle can be constructed only by task_region because it has no public constructors. Thus, run can be invoked (directly or indirectly) only from a user-provided function passed to task_region:

void g();

void f(task_region_handle& tr)
{
    tr.run(g);              // OK, invoked from within task_region in h
}

void h()
{
    task_region(f);
}

int main()
{
    task_region_handle tr;  // Error: no public constructor
    tr.run(g);              // No way to call run outside of a task_region
    return 0;
}

PrevUpHomeNext