У меня проблема с tbb parallel_for()
и task_group::run()
.
У меня есть код, который запускает задачу в потоке, используя task_group::run()
. В этой задаче я использую parallel_for()
для распараллеливания функции.
С другой стороны, в главном потоке я выполняю другие вычисления, и в какой-то момент я также вызываю parallel_for()
для других вещей.
Проблема, с которой я столкнулся, состоит в том, что tbb повторно использует «основной поток» этого второго материала для вызова кода запуска до group
(без вызова wait()
на group
).
В моем случае это создает проблему, я не хочу, чтобы первое задание вызывало какой-либо вызов в основном потоке. Причиной является проблема пользовательского интерфейса, у меня есть код, который проверяет, находимся мы в главном потоке или нет, чтобы обновить некоторые элементы пользовательского интерфейса. И обновление пользовательского интерфейса во время второго parallel_for()
приведет к проблеме в этом конкретном случае.
Вот код, который представляет проблему:
using namespace std::chrono_literals;
tbb::task_group group;
auto mainThreadId = std::this_thread::get_id();
std::atomic<bool> needWait(true);
std::atomic<bool> taskOnThreadFinish(false);
group.run(
[&]
{
eastl::vector<int> values(20, 0);
tbb::parallel_for_each(
values.begin(),
values.end(),
[&](int i)
{
while(needWait)
std::this_thread::sleep_for(1ms);
// Should never, ever, never be call on the main thread, but it could be the case in TBB !!!!!!
assert(mainThreadId != std::this_thread::get_id());
std::this_thread::sleep_for(1ms);
});
taskOnThreadFinish = true;
});
eastl::vector<int> mainThreadValues(10, 0);
tbb::parallel_for_each(
mainThreadValues.begin(),
mainThreadValues.end(),
[&](int i)
{
needWait = false;
std::this_thread::sleep_for(1ms);
});
while(!taskOnThreadFinish)
std::this_thread::sleep_for(1ms);
Так что мой вопрос: как избежать повторного использования основного потока, когда второй вызов tbb :: parallel_for_each () сделан?
Обратите внимание, что код, использующий новую параллельную функцию / поведение std, работает хорошо.
UPDATE
Использование tbb :: task_arena решает проблему, потому что она изолирует task_group внутри арены.
tbb::task_group arena;
tbb::task_group group;
...
arena.execute(
[&]
{
group.Run(
[&]
{
...
});
});