Tasks

Definition:

  • Task construct defines a section of code.

  • Inside a parallel region, a thread encountering a task construct will package up the task for execution.

  • Some thread in the parallel region will execute the task at some point in the future.

#pragma omp task [clauses]
structured-block

Data Sharing:

  • The default for tasks is usually FIRSTPRIVATE, because the task may not be executed until later (and variables may have gone out of scope).

  • Variables that are shared in all constructs starting from the innermost enclosing parallel construct are shared.

#pragma omp parallel shared(A) private(B)
{
    ...
    #pragma omp task
    {
        int C;
        compute(A, B, C); // A is shared, B is firstprivate, C is private
    }
}
  • Getting data attribute scoping right can be quite tricky, using default(none) is a good idea.

Task complete time:

  • At thread barriers, whether explicit or implicit

    • at the end of current parallel region, there is an implicit barrier to all tasks

  • At taskwait directive

    • Wait until all tasks defined in the current task have completed.

    • #pragma omp taskwait

    • Note: applies only to tasks generated in the current task, not to "descendants".

// Example of taskwait: Binary Tree Traversal

void postorder(node* p) {
    if (p->left) {
        #pragma omp task
        {
            postorder(p->left);
        }
    }
    if (p->right) {
        #pragma omp task 
        {
            postorder(p->right);
        }
    }
    #pragma omp taskwait // Parent task suspended until children tasks complete
    process(p->data);
}

Task switching:

  • Certain constructs have task scheduling points at defined locations within them

  • When a thread encounters a task scheduling point, it is allowed to suspend the current task and execute another (called task switching)

  • It can then return to the original task and resume.

  • Example of taskyield from SC15

omp_lock_t *lock;
for (int i = 0; i < n; i++) {
    #pragma omp task
    {
        something_useful();
        while (!omp_test_lock(lock)) {
            #pragma omp taskyield
            // to make full use of computing resources 
            // and avoid deadlock situations.
        }
        something_critical();
        omp_unset_lock(lock);
    }
}

Reference

Last updated