forked from OSchip/llvm-project
[OpenMP] Fix task wait doesn't work as expected in serialized team
As discussed in D107121, task wait doesn't work when a regular task T depends on a detached task or a hidden helper task T' in a serialized team. The root cause is, since the team is serialized, the last task will not be tracked by `td_incomplete_child_tasks`. When T' is finished, it first releases its dependences, and then decrements its parent counter. So far so good. For the thread that is running task wait, if at the moment it is still spinning and trying to execute tasks, it is fine because it can detect the new task and execute it. However, if it happends to finish the function `flag.execute_tasks(...)`, it will be broken because `td_incomplete_child_tasks` is 0 now. In this patch, we update the rule to track children tasks a little bit. If the task team encounters a proxy task or a hidden helper task, all following tasks will be tracked. Reviewed By: AndreyChurbanov Differential Revision: https://reviews.llvm.org/D107496
This commit is contained in:
parent
6c0181c00f
commit
8442967fe3
|
@ -807,6 +807,24 @@ static void __kmp_free_task_and_ancestors(kmp_int32 gtid,
|
|||
gtid, taskdata, children));
|
||||
}
|
||||
|
||||
// Only need to keep track of child task counts if any of the following:
|
||||
// 1. team parallel and tasking not serialized;
|
||||
// 2. it is a proxy or detachable or hidden helper task
|
||||
// 3. the children counter of its parent task is greater than 0.
|
||||
// The reason for the 3rd one is for serialized team that found detached task,
|
||||
// hidden helper task, T. In this case, the execution of T is still deferred,
|
||||
// and it is also possible that a regular task depends on T. In this case, if we
|
||||
// don't track the children, task synchronization will be broken.
|
||||
static bool __kmp_track_children_task(kmp_taskdata_t *taskdata) {
|
||||
kmp_tasking_flags_t flags = taskdata->td_flags;
|
||||
bool ret = !(flags.team_serial || flags.tasking_ser);
|
||||
ret = ret || flags.proxy == TASK_PROXY ||
|
||||
flags.detachable == TASK_DETACHABLE || flags.hidden_helper;
|
||||
ret = ret ||
|
||||
KMP_ATOMIC_LD_ACQ(&taskdata->td_parent->td_incomplete_child_tasks) > 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// __kmp_task_finish: bookkeeping to do when a task finishes execution
|
||||
//
|
||||
// gtid: global thread ID for calling thread
|
||||
|
@ -933,12 +951,9 @@ static void __kmp_task_finish(kmp_int32 gtid, kmp_task_t *task,
|
|||
if (ompt)
|
||||
__ompt_task_finish(task, resumed_task, ompt_task_complete);
|
||||
#endif
|
||||
|
||||
// Only need to keep track of count if team parallel and tasking not
|
||||
// serialized, or task is detachable and event has already been fulfilled
|
||||
if (!(taskdata->td_flags.team_serial || taskdata->td_flags.tasking_ser) ||
|
||||
taskdata->td_flags.detachable == TASK_DETACHABLE ||
|
||||
taskdata->td_flags.hidden_helper) {
|
||||
// TODO: What would be the balance between the conditions in the function
|
||||
// and an atomic operation?
|
||||
if (__kmp_track_children_task(taskdata)) {
|
||||
__kmp_release_deps(gtid, taskdata);
|
||||
// Predecrement simulated by "- 1" calculation
|
||||
#if KMP_DEBUG
|
||||
|
@ -1376,11 +1391,9 @@ kmp_task_t *__kmp_task_alloc(ident_t *loc_ref, kmp_int32 gtid,
|
|||
if (UNLIKELY(ompt_enabled.enabled))
|
||||
__ompt_task_init(taskdata, gtid);
|
||||
#endif
|
||||
// Only need to keep track of child task counts if team parallel and tasking
|
||||
// not serialized or if it is a proxy or detachable or hidden helper task
|
||||
if (flags->proxy == TASK_PROXY || flags->detachable == TASK_DETACHABLE ||
|
||||
flags->hidden_helper ||
|
||||
!(taskdata->td_flags.team_serial || taskdata->td_flags.tasking_ser)) {
|
||||
// TODO: What would be the balance between the conditions in the function and
|
||||
// an atomic operation?
|
||||
if (__kmp_track_children_task(taskdata)) {
|
||||
KMP_ATOMIC_INC(&parent_task->td_incomplete_child_tasks);
|
||||
if (parent_task->td_taskgroup)
|
||||
KMP_ATOMIC_INC(&parent_task->td_taskgroup->count);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// RUN: %libomp-cxx-compile-and-run
|
||||
// RUN: %libomp-cxx-compile && env OMP_NUM_THREADS=1 %libomp-run
|
||||
|
||||
/*
|
||||
* This test aims to check whether hidden helper task can work with regular task
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// RUN: %libomp-cxx-compile-and-run
|
||||
// RUN: %libomp-cxx-compile && env OMP_NUM_THREADS=1 %libomp-run
|
||||
|
||||
/*
|
||||
* This test aims to check whether hidden helper thread has right gtid. We also
|
||||
|
|
Loading…
Reference in New Issue