1

別のノードを起動する必要があるかどうかを決定する条件変数としてノードの出力を使用して、TBB フロー グラフの実行パスを動的に制御することは可能ですか?

4

1 に答える 1

5

メッセージが flow::graph のどこに移動するかを動的に制御するには、いくつかの方法があります。

ノードの本体で、他のノードに明示的にメッセージを送信できます。入力の値に応じて、がまたはにfunc_bodyメッセージを出力することに注意してください。メッセージの流れはグラフのトポロジによって制御されないため、ノードは によって接続されません。f1f2make_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::f1f2multifunction_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);

    // ...
}

現在、これら 2 つの方法は機能的に同一です。それぞれが の本体を実行するタスクを生成しますfunction_nodes。将来的には、multifunction_node出力ポートが 1 つだけの場合はスポーンしないようにケースが最適化される可能性がありますtry_put()

于 2013-07-29T19:42:00.350 に答える