1

我是线程构建块 (TBB) 的新手;我需要用 TBB 节点实现以下逻辑:

N 类型的节点接收两个输入;例如: 1. std::vector // 数据 2. bool // 标志

这些输入是异步的。

如果输入类型为 1,则处理类型为 N 的节点所拥有的数据以产生两个输出,例如: a.标准::向量 b。整数

如果输入是类型 2,则处理类型为 N 的节点所拥有的数据以产生一个输出,例如 std::vector。

我一直在尝试使用 tbb::flow::or_node 来制定输入部分,并使用 tbb::flow::multifunction_node 来制定输出部分。

如果只有一个输入和多个输出,这个逻辑可以用 tbb::flow::multifunction_node 来写(我测试过,可以)。如果有一个输出和多个输入,我找到了说明解决方案的代码示例。但是,我不清楚如何使用 TBB 框架实现多个异步输入和多个输出的情况。欢迎提出建议。

4

1 回答 1

3

您应该能够使用 or_node 的当前实现做您想做的事情。(我们正在重新设计 or_node 的输出以使其更友好,但我们需要像您这样的用户就 or_node 社区预览功能的问题提供意见。)

要记住的一件事是在使用 or_node 编译代码时打开 CPF。开关是 -DTBB_PREVIEW_GRAPH_NODES=1 。

# define TBB_PREVIEW_GRAPH_NODES 1  // necessary to turn on the or_node community Preview Feature.
#include "tbb/flow_graph.h"
#include <vector>

using namespace tbb::flow;

// The output format of the or_node is a struct that contains
//   1. the index of the input that the message appeared on, and
//   2. a tuple, the (i-1)th element of which is the message received

typedef or_node<tuple<std::vector<double>, bool> > my_or_node_type;

// it wasn't clear from the description if you wanted to differentiate between the vectors output with
// an input of type 1. or type 2.  If you need to do that you can add an extra output port to the multifunction_node.
typedef multifunction_node<my_or_node_type::output_type, tuple<std::vector<double>, int> > my_mf_node_type;

struct mf_node_body {
    void operator()(const my_or_node_type::output_type &in, my_mf_node_type::output_ports_type &op) {
        switch(in.indx) {
        case 0: {
                // do the operation for the first input (the std::vector) The vector will be in
                // get<0>(in.result).  Remember you are copying vectors here, so if you have big
                // vectors you will probably want to do some buffer management on your own and
                // pass refs to the vector instead.
            }
            break;
        case 1: {
                // do the operation signaled by the second input (the bool.)  The value of the
                // input is in get<1>(in.result).
            }
            break;
        }
    }
};


main() {
    graph g;
    my_or_node_type multi_in(g);
    my_mf_node_type multi_out(g, unlimited, mf_node_body());

    // if the vector-producing node is called vpn, you attach it to the 0-th input of the or_node with
    //     make_edge(vpn, input_port<0>(multi_in));
    //
    // the bool-producing node bn can be attached similarly:
    //     make_edge(bn, input_port<1>(multi_in);
    //
    // attach the multi-in to the multi-out:
    //     make_edge(multi_in, multi_out);
    //
    // attach the vector consumer node vcn
    //     make_edge(output_port<0>(multi_out), vcn);
    //
    // attach the integer output to the int consuming node icn
    //     make_edge(output_port<1>(multi_out), icn);
    // 
    // start up the graph and make sure to do a wait_for_all() at the end.
}

请记住,multifunction_node 主体是并行调用的,因此它所做的工作不应该有竞争条件(除非您出于某种原因需要serial竞争条件。)您可以通过构造它来使节点主体串行执行而不是unlimited. 确保您可以安全地销毁图表的唯一方法是确保没有任务正在执行任何节点。最好的方法是做一个g.wait_for_all().

问候,克里斯

PS - 一份附录。如果定义了 multifunction_node serial,它将有一个输入缓冲区,除非您明确排除它。如果您不希望缓冲区存在,这可能会改变图形的行为。

于 2013-11-20T20:19:59.477 回答