oneTBB
oneTBB copied to clipboard
task_group::wait() waits for tasks in unrelated task groups
Documentation for task_group::wait()
is succinct and states that it "waits for all tasks in the group to complete or be cancelled". However, this is not exactly correct, because this function will also wait for tasks added to unrelated task groups. Consider this example (downloadable code here: https://github.com/p12tic/tbb_task_group_wait_bug/blob/master/task.cc):
#include <tbb/task_group.h>
#include <iostream>
#include <thread>
int main()
{
tbb::task_group b;
{
tbb::task_group a;
a.run([]()
{
std::cout << "A1 start" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "A1 end" << std::endl;
});
b.run([]()
{
std::cout << "B1 start" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(4));
std::cout << "B1 end" << std::endl;
});
a.wait();
b.run([]()
{
std::cout << "B2 start" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(4));
std::cout << "B2 end" << std::endl;
});
}
b.wait();
}
One would expect that A1 task is scheduled, then B1 task is scheduled, then after A1 task finishes in a.wait()
, B2 is scheduled while B1 is still running. Unfortunately, the line a.wait()
waits for both A1 and B1. Wrapping task.run()
inside task.run()
like this doesn't help (code here: https://github.com/p12tic/tbb_task_group_wait_bug/blob/master/task_in_task.cc):
a.run([&]()
{
a.run([]()
{
std::cout << "A1 start" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "A1 end" << std::endl;
});
});
I'm posting the above just because it was a workaround to unrelated problem suggested by an Intel engineer somewhere I can't find now.
A possible workaround is to create a task arena, associate functions with task groups via task_group::defer
and then schedule them via task_arena::enqueue
(code here: https://github.com/p12tic/tbb_task_group_wait_bug/blob/master/enqueue_defer.cc)
This bug happens on both 2020.3 and latest master.
If using defer+enqueue
is the recommended approach, then this should be expressed in the specification. I could make a PR to improve documentation if this is deemed to be the solution.
Basically, this is problem of task_group::wait()
description. There is no mention that the thread executing task_group::wait()
might participate in another tasks that are not related to particular task_group.
@pavelkumbrasev I think we should update the description in the Specs https://spec.oneapi.io/versions/latest/elements/oneTBB/source/task_scheduler/task_group/task_group_cls.html What do you think?
@p12tic is this issue still relevant?
The project migrated off oneAPI, so the bug is no longer a pain.
The reproduction code is present in the issue, so it's not hard to try if it still doesn't work.