36 std::enable_if_t<is_static_task_v<C>,
Task>
emplace(C&& callable);
48 std::enable_if_t<is_dynamic_task_v<C>,
Task>
emplace(C&& callable);
60 std::enable_if_t<is_condition_task_v<C>,
Task>
emplace(C&& callable);
73 std::enable_if_t<is_cudaflow_task_v<C>,
Task>
emplace(C&& callable);
85 template <
typename... C, std::enable_if_t<(
sizeof...(C)>1),
void>* =
nullptr>
117 template <
typename I,
typename C>
140 std::enable_if_t<std::is_integral<std::decay_t<I>>::value,
void>* =
nullptr 143 I beg, I end, I step, C&& callable,
size_t chunk = 1
166 std::enable_if_t<std::is_floating_point<std::decay_t<I>>::value,
void>* =
nullptr 169 I beg, I end, I step, C&& callable,
size_t chunk = 1
189 template <
typename I,
typename T,
typename B>
207 template <
typename I,
typename T>
225 template <
typename I,
typename T>
249 template <
typename I,
typename T,
typename B,
typename U>
276 template <
typename I,
typename T,
typename B,
typename P,
typename U>
278 I beg, I end, T& result, B&& bop1, P&& bop2, U&& uop
346 template <
typename L>
356 template <
typename... C, std::enable_if_t<(
sizeof...(C)>1),
void>*>
358 return std::make_tuple(
emplace(std::forward<C>(cs))...);
363 template <
typename C>
365 auto n = _graph.emplace_back(
366 nstd::in_place_type_t<Node::StaticWork>{}, std::forward<C>(c)
373 template <
typename C>
375 auto n = _graph.emplace_back(
376 nstd::in_place_type_t<Node::DynamicWork>{}, std::forward<C>(c)
383 template <
typename C>
385 auto n = _graph.emplace_back(
386 nstd::in_place_type_t<Node::ConditionWork>{}, std::forward<C>(c)
391 #ifdef TF_ENABLE_CUDA 394 template <
typename C>
396 auto n = _graph.emplace_back(
397 nstd::in_place_type_t<Node::cudaFlowWork>{}, std::forward<C>(c)
405 auto node = _graph.emplace_back(
406 nstd::in_place_type_t<Node::ModuleWork>{}, &taskflow
413 from._node->_precede(to._node);
432 for(
auto from : froms) {
439 for(
auto from : froms) {
446 auto node = _graph.emplace_back();
451 template <
typename I,
typename C>
453 I beg, I end, C&& c,
size_t chunk
466 size_t remain = std::distance(beg, end);
472 auto x = std::min(remain, chunk);
477 auto task =
emplace([beg, e, c] ()
mutable {
478 std::for_each(beg, e, c);
489 if(S.num_successors() == 0) {
493 return std::make_pair(S, T);
500 std::enable_if_t<std::is_integral<std::decay_t<I>>::value,
void>*
504 if((s == 0) || (beg < end && s <= 0) || (beg > end && s >=0) ) {
505 TF_THROW(
"invalid range [", beg,
", ", end,
") with step size ", s);
519 auto o =
static_cast<I
>(chunk) * s;
520 auto e = std::min(beg + o, end);
521 auto task =
emplace([=] ()
mutable {
522 for(
auto i=beg; i<e; i+=s) {
526 source.precede(task);
527 task.precede(target);
534 auto o =
static_cast<I
>(chunk) * s;
535 auto e = std::max(beg + o, end);
536 auto task =
emplace([=] ()
mutable {
537 for(
auto i=beg; i>e; i+=s) {
541 source.precede(task);
542 task.precede(target);
547 if(source.num_successors() == 0) {
548 source.precede(target);
551 return std::make_pair(source, target);
555 template <
typename I,
typename C,
556 std::enable_if_t<std::is_floating_point<std::decay_t<I>>::value,
void>*
560 if((s == 0) || (beg < end && s <= 0) || (beg > end && s >=0) ) {
561 TF_THROW(
"invalid range [", beg,
", ", end,
") with step size ", s);
576 for(I e=beg; e<
end; e+=s) {
578 auto task =
emplace([=] ()
mutable {
579 for(
size_t i=0; i<N; ++i, b+=s) {
583 source.precede(task);
584 task.precede(target);
591 auto task =
emplace([=] ()
mutable {
592 for(
size_t i=0; i<N; ++i, b+=s) {
596 source.precede(task);
597 task.precede(target);
603 for(I e=beg; e>
end; e+=s) {
605 auto task =
emplace([=] ()
mutable {
606 for(
size_t i=0; i<N; ++i, b+=s) {
610 source.precede(task);
611 task.precede(target);
618 auto task =
emplace([=] ()
mutable {
619 for(
size_t i=0; i<N; ++i, b+=s) {
623 source.precede(task);
624 task.precede(target);
628 if(source.num_successors() == 0) {
629 source.precede(target);
637 template <
typename I,
typename T>
639 return reduce(beg, end, result, [] (
const auto& l,
const auto& r) {
640 return std::min(l, r);
646 template <
typename I,
typename T>
648 return reduce(beg, end, result, [] (
const auto& l,
const auto& r) {
649 return std::max(l, r);
654 template <
typename I,
typename T,
typename B,
typename U>
656 I beg, I end, T& result, B&& bop, U&& uop
662 size_t d = std::distance(beg, end);
664 size_t g = std::max((d + w - 1) / w,
size_t{2});
670 auto g_results = std::make_unique<T[]>(w);
679 size_t x = std::min(remain, g);
684 auto task =
emplace([beg, e, bop, uop, res=&(g_results[
id])] ()
mutable {
686 for(++beg; beg != e; ++beg) {
687 *res = bop(std::move(*res), uop(*beg));
691 source.precede(task);
692 task.precede(target);
700 target.work([&result, bop, res=make_moc(std::move(g_results)), w=
id] () {
701 for(
auto i=0u; i<w; i++) {
702 result = bop(std::move(result), res.object[i]);
706 return std::make_pair(source, target);
710 template <
typename I,
typename T,
typename B,
typename P,
typename U>
712 I beg, I end, T& result, B&& bop, P&& pop, U&& uop
718 size_t d = std::distance(beg, end);
720 size_t g = std::max((d + w - 1) / w,
size_t{2});
725 auto g_results = std::make_unique<T[]>(w);
734 size_t x = std::min(remain, g);
739 auto task =
emplace([beg, e, uop, pop, res= &g_results[
id]] ()
mutable {
741 for(++beg; beg != e; ++beg) {
742 *res = pop(std::move(*res), *beg);
745 source.precede(task);
746 task.precede(target);
754 target.work([&result, bop, g_results=make_moc(std::move(g_results)), w=
id] () {
755 for(
auto i=0u; i<w; i++) {
756 result = bop(std::move(result), std::move(g_results.object[i]));
760 return std::make_pair(source, target);
764 template <
typename L>
765 void FlowBuilder::_linearize(L& keys) {
767 auto itr = keys.begin();
768 auto end = keys.end();
776 for(++nxt; nxt != end; ++nxt, ++itr) {
777 itr->_node->_precede(nxt->_node);
792 template <
typename I,
typename T,
typename B>
797 size_t d = std::distance(beg, end);
799 size_t g = std::max((d + w - 1) / w,
size_t{2});
805 auto g_results = std::make_unique<T[]>(w);
815 size_t x = std::min(remain, g);
821 auto task =
emplace([beg, e, op, res = &g_results[
id]] ()
mutable {
823 for(++beg; beg != e; ++beg) {
824 *res = op(std::move(*res), *beg);
832 source.precede(task);
833 task.precede(target);
847 target.work([g_results=make_moc(std::move(g_results)), &result, op, w=
id] () {
848 for(
auto i=0u; i<w; i++) {
849 result = op(std::move(result), g_results.object[i]);
853 return std::make_pair(source, target);
871 template <
typename... Args>
896 bool _detached {
false};
900 template <
typename... Args>
void linearize(std::vector< Task > &tasks)
adds adjacent dependency links to a linear list of tasks
Definition: flow_builder.hpp:782
void broadcast(Task A, std::vector< Task > &others)
adds dependency links from one task A to many tasks
Definition: flow_builder.hpp:417
std::pair< Task, Task > transform_reduce(I beg, I end, T &result, B &&bop, U &&uop)
constructs a task dependency graph of parallel transformation and reduction
Definition: flow_builder.hpp:655
void succeed(std::vector< Task > &others, Task A)
adds dependency links from many tasks to one task A
Definition: flow_builder.hpp:431
T hardware_concurrency(T... args)
Task placeholder()
creates an empty task
Definition: flow_builder.hpp:445
Subflow(Args &&... args)
constructs a subflow builder object
Definition: flow_builder.hpp:901
void detach()
enables the subflow to detach from its parent task
Definition: flow_builder.hpp:911
bool detached() const
queries if the subflow will be detached from its parent task
Definition: flow_builder.hpp:916
std::pair< Task, Task > reduce_max(I beg, I end, T &result)
constructs a task dependency graph of parallel reduction through std::max
Definition: flow_builder.hpp:647
Task & succeed(Ts &&... tasks)
adds precedence links from other tasks to this
Definition: task.hpp:362
std::enable_if_t< is_static_task_v< C >, Task > emplace(C &&callable)
creates a static task from a given callable object
Definition: flow_builder.hpp:364
std::pair< Task, Task > parallel_for(I beg, I end, C &&callable, size_t chunk=1)
constructs a task dependency graph of range-based parallel_for
Definition: flow_builder.hpp:452
Task composed_of(Taskflow &taskflow)
creates a module task from a taskflow
Definition: flow_builder.hpp:404
void precede(Task A, Task B)
adds a dependency link from task A to task B
Definition: flow_builder.hpp:412
main entry to create a task dependency graph
Definition: taskflow.hpp:18
FlowBuilder(Graph &graph)
constructs a flow builder object
Definition: flow_builder.hpp:351
building methods of a task dependency graph
Definition: flow_builder.hpp:13
bool joined() const
queries if the subflow will join its parent task
Definition: flow_builder.hpp:921
handle to a node in a task dependency graph
Definition: task.hpp:113
Task & precede(Ts &&... tasks)
adds precedence links from this to other tasks
Definition: task.hpp:339
std::pair< Task, Task > reduce(I beg, I end, T &result, B &&bop)
construct a task dependency graph of parallel reduction
Definition: flow_builder.hpp:793
building methods of a subflow graph in dynamic tasking
Definition: flow_builder.hpp:864
void join()
enables the subflow to join its parent task
Definition: flow_builder.hpp:906
std::pair< Task, Task > reduce_min(I beg, I end, T &result)
constructs a task dependency graph of parallel reduction through std::min
Definition: flow_builder.hpp:638