-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Add the document describing isolated_task_group #1778
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall looks good to me but I found a few minor issues.
|
||
## Introduction | ||
|
||
In-arena task isolation scopes were introduced into TBB to restrict task stealing within arena |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In-arena task isolation scopes were introduced into TBB to restrict task stealing within arena | |
[In-arena task isolation scopes](https://oneapi-spec.uxlfoundation.org/specifications/oneapi/latest/elements/onetbb/source/task_scheduler/task_arena/this_task_arena_ns) were introduced into TBB to restrict task stealing within an arena |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tbb::task_group tg; | ||
mutex init_mtx; | ||
parallel_XXXL { // pipeline, FG | ||
while (!initialized(some_obj)) { | ||
if (try_lock(init_mtx)) { | ||
tg.run_and_wait { | ||
initialize(some_obj); // uses parallel_for, etc. | ||
}; | ||
unlock(init_mtx); | ||
} else { tg.wait(); } | ||
} | ||
... // do the work that uses some_obj | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can it make sense for two isolated_task_group
s to share one isolation tag?
I thought of the case of having two objects A
and B
, both are lazy initialized using the pattern described, but using the isolated_task_group
. But an object B
needs A
to be initialized before running the parallel phase of the initialization:
A::initialize() { parallel_for(...) }
B::initialize() {
A& a = getA();
parallel_for(...);
}
A& getA() {
while (!initialized(a_obj)) {
if (try_lock(a_mutex)) {
a_isolated_tg.run_and_wait( { initialize(a_obj); });
unlock(a_mutex);
} else { a_isolated_tg.wait(); }
}
return a_obj;
}
B& getB() { /*same as getA, but using b_mutex, b_isolated_tg and b_obj*/ }
int main() {
parallel_for( {
B& b = getB();
})
}
As far as I understand, workers performing tasks of the parallel_for
in main
will be able to help initializing B
.
But would they be able to help initializing A
, as it is required to initialize B
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the initialization of A is in its own isolation scope and is called only once in B::initialize
- then no, threads that call getB
will not be able to help with initializing A. It is prevented by the implementation mechanics: a task dispatcher that runs in an isolation scope can only take tasks with that scope's tag, not any other tasks.
If however getA
would be called in the parallel loop of B::initialize
, then threads working on that loop could possibly enter the isolation scope in getA
and help.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just thought if it makes sense to have API in the future that allow sharing the same isolation for several task_group
s?
In my understanding, in this example having a_isolated_tg
and b_isolated_tg
to share the same isolation tag will allow workers in main
's parallel_for
to participate in A
initialization as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sharing the same tag means having no isolation between layers, in this case between A::initialize
and B::initialize
. If that's the goal, the simplest thing is to use a regular task group for A.
I guess you might want to allow B::initialize
to take tasks from A::initialize
, but not vice versa - i.e., to have one-way isolation. The current implementation of isolated tasks simply does not allow to do that. For that to be possible, we would need something similar to the binding of task_group_contexts.
Updated: perhaps even something more complicated, because task_group_contexts form a tree, but with task groups it is not hard to build "isolation DAGs". Imagine in the example above there is an object C which lazy initialization also needs A. That means, A::initialize
can be "nested" into both B::initialize
and C::initialize
at the same time.
Co-authored-by: Mike Voss <[email protected]>
a49c69f
to
7cffbc5
Compare
This PR adds the "RFC"/design document for
isolated_task_group
as an experimental feature of the library.