С помощью TBB вы можете создать хороший DAG задач, и он может автоматически запускать их параллельно. Пример из документации:
typedef continue_node< continue_msg > node_t;
typedef const continue_msg & msg_t;
int main() {
tbb::flow::graph g;
node_t A(g, [](msg_t){ a(); } );
node_t B(g, [](msg_t){ b(); } );
node_t C(g, [](msg_t){ c(); } );
node_t D(g, [](msg_t){ d(); } );
node_t E(g, [](msg_t){ e(); } );
node_t F(g, [](msg_t){ f(); } );
make_edge(A, B);
make_edge(B, C);
make_edge(B, D);
make_edge(A, E);
make_edge(E, D);
make_edge(E, F);
A.try_put( continue_msg() );
g.wait_for_all();
return 0;
}
Это работает нормально, однако предполагается, что у меня есть какой-то хорошо известный корневой узел, и все узлы являются зависимыми от этого узла. Что, если у меня есть более общая сеть, в которой может быть несколько корневых узлов?
int main() {
tbb::flow::graph g;
// Imagine a function did this but in a generic way:
node_t A(g, [](msg_t){ a(); } );
node_t B(g, [](msg_t){ b(); } );
node_t C(g, [](msg_t){ c(); } );
node_t D(g, [](msg_t){ d(); } );
node_t E(g, [](msg_t){ e(); } );
node_t F(g, [](msg_t){ f(); } );
make_edge(A, B);
make_edge(B, C);
make_edge(D, E);
// Now how do I now do this?
A.try_put( continue_msg() );
D.try_put( continue_msg() );
F.try_put( continue_msg() );
g.wait_for_all();
return 0;
}
Я надеюсь, что этот пример понятен - в основном у меня масса задач, но зависимости между ними динамические, поэтому они могут вообще не зависеть друг от друга. Как мне сказать TBB: «Хорошо, я хочу, чтобы все эти задачи выполнялись».
(Очевидно, я могу вручную подсчитать количество зависимостей для каждой задачи, но я спрашиваю, делает ли это уже TBB.)
Обновлено: чтобы прояснить, я спрашиваю, есть ли функция, при которой автоматически запускает все корневые узлы. Очевидно, я могу сделать это вручную - это то, что делает пример выше!
Да, я знаю. Мой вопрос не в том, «как я могу запустить несколько корневых узлов», а в том, «есть ли функция, позволяющая автоматически находить все корневые узлы и запускать их».
Тогда, к сожалению, в Flow Graph нет такой встроенной функциональности.





Вероятно, это недоразумение по поводу самого flow::graph. Вы должны указать зависимости программно, добавив дуги между узлами. Вы try_put к первому узлу графа, чтобы запустить его. Это единственный способ начать график.
Если у вас есть внешние события, которые вы хотите запустить для графика, вы должны создать слушателя этого события, который try_puts запускает график.
Вы можете создать multifunction_node, который никогда не возвращается, который вы можете использовать для поиска событий и отправки сообщений, но это плохой дизайн TBB. Вы бы навсегда заблокировали задачу TBB для этого multifunction_node, нет-нет. И вам еще нужно что-то try_put к multifunction_node, чтобы он запустился.
Я думаю, вы неправильно поняли мой вопрос. Мне нужна функция, которая автоматически находит A, D и F и запускает их.
Нет проблем с несколькими «корневыми узлами», поскольку все они равны, и задача создается и запускается для каждого вызова
try_put, даже еслиg.wait_for_allеще не был выполнен. Объектgraphобрабатывает ссылки для всех узлов. Итак, когда все узлы обработаны и в графе нет работы,wait_for_all()служит точкой синхронизации и вернется. Вы даже можете создавать новые ребра во время обработки графа.