taskgroup Construct
5.5. taskgroup Construct#
In this example, tasks are grouped and synchronized using the taskgroup construct.
Initially, one task (the task executing the start_background_work() call) is created in the parallel region, and later a parallel tree traversal is started (the task executing the root of the recursive compute_tree() calls). While synchronizing tasks at the end of each tree traversal, using the taskgroup construct ensures that the formerly started background task does not participate in the synchronization and is left free to execute in parallel. This is opposed to the behavior of the taskwait construct, which would include the background tasks in the synchronization.
//%compiler: clang
//%cflags: -fopenmp
/*
* name: taskgroup.1
* type: C
* version: omp_4.0
*/
extern void start_background_work(void);
extern void check_step(void);
extern void print_results(void);
struct tree_node
{
struct tree_node *left;
struct tree_node *right;
};
typedef struct tree_node* tree_type;
extern void init_tree(tree_type);
#define max_steps 100
void compute_something(tree_type tree)
{
// some computation
}
void compute_tree(tree_type tree)
{
if (tree->left)
{
#pragma omp task
compute_tree(tree->left);
}
if (tree->right)
{
#pragma omp task
compute_tree(tree->right);
}
#pragma omp task
compute_something(tree);
}
int main()
{
int i;
tree_type tree;
init_tree(tree);
#pragma omp parallel
#pragma omp single
{
#pragma omp task
start_background_work();
for (i = 0; i < max_steps; i++)
{
#pragma omp taskgroup
{
#pragma omp task
compute_tree(tree);
} // wait on tree traversal in this step
check_step();
}
} // only now is background work required to be complete
print_results();
return 0;
}
!!%compiler: gfortran
!!%cflags: -fopenmp
! name: taskgroup.1
! type: F-free
! version: omp_4.0
module tree_type_mod
integer, parameter :: max_steps=100
type tree_type
type(tree_type), pointer :: left, right
end type
contains
subroutine compute_something(tree)
type(tree_type), pointer :: tree
! some computation
end subroutine
recursive subroutine compute_tree(tree)
type(tree_type), pointer :: tree
if (associated(tree%left)) then
!$omp task
call compute_tree(tree%left)
!$omp end task
endif
if (associated(tree%right)) then
!$omp task
call compute_tree(tree%right)
!$omp end task
endif
!$omp task
call compute_something(tree)
!$omp end task
end subroutine
end module
program main
use tree_type_mod
type(tree_type), pointer :: tree
call init_tree(tree);
!$omp parallel
!$omp single
!$omp task
call start_background_work()
!$omp end task
do i=1, max_steps
!$omp taskgroup
!$omp task
call compute_tree(tree)
!$omp end task
!$omp end taskgroup ! wait on tree traversal in this step
call check_step()
enddo
!$omp end single
!$omp end parallel ! only now is background work required to be complete
call print_results()
end program