TBB потоковый граф условного исполнения

Можно динамически контролировать путь выполнения в графе потоков TBB, используя вывод узла в качестве переменной условия, чтобы определить, следует ли запускать другой узел?

1

Решение

Есть несколько способов динамически контролировать, куда сообщения идут в потоке :: graph:

Вы можете явно помещать сообщения в другие узлы в теле узла. Заметить, что func_body помещает сообщение f1 или же f2в зависимости от стоимости его ввода. Узлы не присоединены 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 (обратите внимание на типы tuple а также get шаблоны находятся в tbb::flow пространство имен, а не std:: как в старой документации.) Обратите внимание, в этом случае мы прилагаем f1 а также f2 к выходным портам 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_node регистр может быть оптимизирован, чтобы не порождать, если только один выходной порт try_put() к.

5

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]