我正在tbb::parallel_for_each中深入运行task_grouptask_group被取消,这似乎导致tbb::parallel_for_each在不满足其后置条件的情况下退出。这是最小的测试用例:

tbb::task_group g;
std::vector<int> x { 0, 0, 0, 0 };
std::atomic<std::size_t> counter {0};
g.run([&x, &counter]() {
    std::cout << "in run()\n" << std::flush;
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
    std::cout << "in run(): slept\n" << std::flush;
    assert(tbb::task::self().is_cancelled());

    tbb::parallel_for_each(x, [&counter](int& y) {
        std::cout << "in run(): in parallel_for_each\n" << std::flush;
        ++y;
        ++counter;
    });
    assert(counter == x.size());
});
std::cout << "canceling\n" << std::flush;
g.cancel();
std::cout << "canceled " << g.is_canceling() << " " << tbb::task::self().is_cancelled() << std::endl;
assert(g.is_canceling());
std::cout << "canceled " << g.is_canceling() << " " << tbb::task::self().is_cancelled() << std::endl;
g.wait();
std::cout << "canceled " << g.is_canceling() << " " << tbb::task::self().is_cancelled() << std::endl;

也就是说:它在等待0.1秒然后循环遍历 vector 的函数上具有tbb::task_group调用run。它计算循环执行的迭代次数。然后cancel()任务组。输出是
canceling
in run()
canceled 1 0
canceled 1 0
in run(): slept
Assertion failed: (counter == x.size()), function operator(), file test.cpp

这就是说,内循环永远不会发生。不过,令我惊讶的是tbb::parallel_for_each的调用没有异常(exception)地退出了,但是它的后置条件(执行循环)没有被满足!
  • 这是预期的行为吗?该文档没有任何警告:https://software.intel.com/en-us/node/506160
  • 如何检查此行为?如果我想确定它确实完成了工作,是否总是需要在调用tbb::task::self().is_cancelled()之后检查tbb::parallel_for_each
  • 在这种情况下,tbb::parallel_for_each是否不应该引发异常(或至少返回bool)?

  • 我可以使用隔离的上下文(https://software.intel.com/en-us/node/506075)“修复”此问题,如下所示:
        tbb::task_group_context root(tbb::task_group_context::isolated);
        tbb::parallel_for_each(x, [&counter](int& y) {
            std::cout << "in run(): in parallel_for_each\n" << std::flush;
            ++y;
            ++counter;
        }, root);
    

    但是目前,我不确定何时可以信任tbb::parallel_for_each来完成其工作。

    最佳答案

    在任务组中,对tbb::parallel_for_each的调用从属于任务组的上下文。

    取消该任务组将取消它以及所有下级任务组。我找不到在文档“下级任务组”中定义的位置,但它似乎是“任务树”中该组下的组。

    取消的tbb::parallel_for_each不能保证其所有迭代都已完成。没有违反发布条件。

    您取消了任务组,该任务组取消了从属tbb::parallel_for_each的隐式任务组,因此它不执行任何操作。

    隔离的上下文可防止取消传播到每个任务组的并行操作中。您可以通过在调用root之前取消parallel_for_each来在该代码中复制效果。

    关于c++ - tbb::parallel_for_each取消时未执行,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59846340/

    10-12 01:49