【问题标题】:Wait for one node in a flow graph? / Pull-based execution?等待流程图中的一个节点? / 基于拉的执行?
【发布时间】:2020-06-01 13:59:29
【问题描述】:

我有一个包含几个端点的图表:f0(g(x))f1(g(x))。我可以制作一个边缘从gf0gf1 的图形,但如果我这样做wait_for_all(),它将计算f0f1。但有时我只想知道f0(x),有时我想知道f1(x),有时我想知道两者。假设gf0f1 的计算成本都很高,我希望能够构建一个图表并调用y0 = f0.run_and_wait(),然后更早、更晚或几乎同时调用@987654336 @。

一种方法是不使用 tbb 流图,而是让 f0f1 都调用 g,但这意味着两次调用 g。另一种方法是让g 进行内部缓存,但是如果对g 的两个调用同时发生,则要么两个线程都工作,要么一个线程阻塞而另一个线程工作。我的理解是,这违背了 tbb 的非阻塞任务概念。

我认为也许有一种方法可以使用async_node 来允许一个线程阻塞g,但这感觉就像一个杂物。

有没有一种方法可以让节点按需从其父节点中拉取?

【问题讨论】:

    标签: tbb tbb-flow-graph


    【解决方案1】:

    你有没有想过在那里使用parallel_fortask_group

    G g(const X &x);
    void f0(const G& g);
    void f1(const G& g);
    
    void runAndWait(const X &x, std::initializer_list<void (*)(const G&)> functions) {
      tbb::task_group g;
      g.run_and_wait([&]() {
        G intermediate = g(x);
        tbb::parallel_for_each(functions, [&](auto &f) {
          f(intermediate);
        });
      });
    }
    

    parallel_for_each 将根据需要生成任务。您只会调用一次g,之后是一次还是两次调用取决于初始化列表的大小。

    【讨论】:

    • 谢谢。总的来说,这是一个很好的模式。它绕过了tbb::task_group 的陷阱,这可能是危险的 WRT 异常。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-02-22
    • 2021-03-29
    • 1970-01-01
    • 1970-01-01
    • 2021-08-15
    • 1970-01-01
    • 2019-06-28
    相关资源
    最近更新 更多