TBB流程图条件执行

时间:2013-07-23 19:15:14

标签: c++ multithreading asynchronous tbb tbb-flow-graph

可以动态控制TBB Flow Graph中的执行路径,使用节点输出作为条件变量来确定是否应该启动另一个节点?

1 个答案:

答案 0 :(得分:5)

有几种方法可以动态控制消息在flow :: graph中的位置:

您可以将消息显式地放入节点主体中的其他节点。请注意,func_body会向f1f2发送消息,具体取决于其输入值。节点未由make_edge()附加,因为消息流不受图表拓扑控制:

template<typename T>
struct func_body {
    typedef tbb::flow::function_node<T,T> target_node_type;
    target_node_type &my_n1;
    target_node_type &my_n2;
    func_body(target_node_type &node1, target_node_type &node2) : my_n1(node1), my_n2(node2) {}
    tbb::flow::continue_msg operator()(const T& in) {
        // do some computation
        bool send_to_one = in > 0;
        if(send_to_one) my_n1.try_put(in);
        else            my_n2.try_put(in);
        return tbb::flow::continue_msg();  // message is discarded if no successor exists
    }
};

struct otherbody {
    int operator()(const int& in) {
        return in;
    }
};

int
main() {
    tbb::flow::graph g;
    tbb::flow::function_node<int,int> f1(g, tbb::flow::unlimited, otherbody());
    tbb::flow::function_node<int,int> f2(g, tbb::flow::unlimited, otherbody());
    tbb::flow::function_node<int> cn(g, tbb::flow::unlimited, func_body<int>(f1,f2));
}

或者您可以使用multifunction_node(请注意tupleget模板的类型位于tbb::flow命名空间中,而不是std::中旧文档。)请注意,在这种情况下,我们会将f1f2附加到multifunction_node的输出端口。

typedef tbb::flow::multifunction_node<int,tbb::flow::tuple<int,int> > mfnode;

struct mfunc_body {
    void operator()(const int& in, mfnode::output_ports_type &op) {
        // do some computation
        bool send_to_one = in > 0;
        if(send_to_one) tbb::flow::get<0>(op).try_put(in);
        else            tbb::flow::get<1>(op).try_put(in);
    }
};

struct otherbody {
    int operator()(const int& in) {
        return in;
    }
};

int
main() {
    tbb::flow::graph g;
    tbb::flow::function_node<int,int> f1(g, tbb::flow::unlimited, otherbody());
    tbb::flow::function_node<int,int> f2(g, tbb::flow::unlimited, otherbody());
    mfnode cn(g, tbb::flow::unlimited, mfunc_body());
    tbb::flow::make_edge(tbb::flow::output_port<0>(cn), f1);
    tbb::flow::make_edge(tbb::flow::output_port<1>(cn), f2);

    // ...
}

目前这两种方法功能相同;每个都会产生一个任务来执行function_nodes的主体。将来,如果只有一个输出端口为multifunction_nodetry_put()情况可能会被优化为不会产生。