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);
71 template <
typename... C, std::enable_if_t<(
sizeof...(C)>1),
void>* =
nullptr>
99 template <
typename I,
typename C>
122 std::enable_if_t<std::is_integral<std::decay_t<I>>::value,
void>* =
nullptr 125 I beg, I end, I step, C&& callable,
size_t chunk = 1
148 std::enable_if_t<std::is_floating_point<std::decay_t<I>>::value,
void>* =
nullptr 151 I beg, I end, I step, C&& callable,
size_t chunk = 1
171 template <
typename I,
typename T,
typename B>
189 template <
typename I,
typename T>
207 template <
typename I,
typename T>
231 template <
typename I,
typename T,
typename B,
typename U>
258 template <
typename I,
typename T,
typename B,
typename P,
typename U>
260 I beg, I end, T& result, B&& bop1, P&& bop2, U&& uop
328 template <
typename L>
351 template <
typename... Args>
367 bool detached()
const;
376 bool _detached {
false};
380 template <
typename... Args>
410 template <
typename... C, std::enable_if_t<(
sizeof...(C)>1),
void>*>
417 template <
typename C>
419 auto n = _graph.emplace_back(
420 nstd::in_place_type_t<Node::StaticWork>{}, std::forward<C>(c)
427 template <
typename C>
429 auto n = _graph.emplace_back(nstd::in_place_type_t<Node::DynamicWork>{},
430 [c=std::forward<C>(c)] (
Subflow& fb)
mutable {
432 if(fb._graph.empty()) {
441 template <
typename C>
443 auto n = _graph.emplace_back(
444 nstd::in_place_type_t<Node::ConditionWork>{}, std::forward<C>(c)
485 auto node = _graph.emplace_back(
486 nstd::in_place_type_t<Node::ModuleWork>{}, &taskflow
493 from._node->_precede(to._node);
512 for(
auto from : froms) {
519 for(
auto from : froms) {
526 auto node = _graph.emplace_back();
531 template <
typename I,
typename C>
533 I beg, I end, C&& c,
size_t chunk
557 auto task =
emplace([beg, e, c] ()
mutable {
569 if(S.num_successors() == 0) {
580 std::enable_if_t<std::is_integral<std::decay_t<I>>::value,
void>*
584 if((s == 0) || (beg < end && s <= 0) || (beg > end && s >=0) ) {
585 TF_THROW(
"invalid range [", beg,
", ", end,
") with step size ", s);
599 auto o =
static_cast<I
>(chunk) * s;
601 auto task =
emplace([=] ()
mutable {
602 for(
auto i=beg; i<e; i+=s) {
606 source.precede(task);
607 task.precede(target);
614 auto o =
static_cast<I
>(chunk) * s;
616 auto task =
emplace([=] ()
mutable {
617 for(
auto i=beg; i>e; i+=s) {
621 source.precede(task);
622 task.precede(target);
627 if(source.num_successors() == 0) {
628 source.precede(target);
635 template <
typename I,
typename C,
636 std::enable_if_t<std::is_floating_point<std::decay_t<I>>::value,
void>*
640 if((s == 0) || (beg < end && s <= 0) || (beg > end && s >=0) ) {
641 TF_THROW(
"invalid range [", beg,
", ", end,
") with step size ", s);
656 for(I e=beg; e<end; e+=s) {
658 auto task =
emplace([=] ()
mutable {
659 for(
size_t i=0; i<N; ++i, b+=s) {
663 source.precede(task);
664 task.precede(target);
671 auto task =
emplace([=] ()
mutable {
672 for(
size_t i=0; i<N; ++i, b+=s) {
676 source.precede(task);
677 task.precede(target);
683 for(I e=beg; e>end; e+=s) {
685 auto task =
emplace([=] ()
mutable {
686 for(
size_t i=0; i<N; ++i, b+=s) {
690 source.precede(task);
691 task.precede(target);
698 auto task =
emplace([=] ()
mutable {
699 for(
size_t i=0; i<N; ++i, b+=s) {
703 source.precede(task);
704 task.precede(target);
708 if(source.num_successors() == 0) {
709 source.precede(target);
717 template <
typename I,
typename T>
719 return reduce(beg, end, result, [] (
const auto& l,
const auto& r) {
726 template <
typename I,
typename T>
728 return reduce(beg, end, result, [] (
const auto& l,
const auto& r) {
734 template <
typename I,
typename T,
typename B,
typename U>
736 I beg, I end, T& result, B&& bop, U&& uop
744 size_t g =
std::max((d + w - 1) / w,
size_t{2});
750 auto g_results = std::make_unique<T[]>(w);
764 auto task =
emplace([beg, e, bop, uop, res=&(g_results[
id])] ()
mutable {
766 for(++beg; beg != e; ++beg) {
771 source.precede(task);
772 task.precede(target);
780 target.work([&result, bop, res=make_moc(
std::move(g_results)), w=
id] () {
781 for(
auto i=0u; i<w; i++) {
782 result = bop(
std::move(result), res.object[i]);
790 template <
typename I,
typename T,
typename B,
typename P,
typename U>
792 I beg, I end, T& result, B&& bop, P&& pop, U&& uop
800 size_t g =
std::max((d + w - 1) / w,
size_t{2});
805 auto g_results = std::make_unique<T[]>(w);
819 auto task =
emplace([beg, e, uop, pop, res= &g_results[
id]] ()
mutable {
821 for(++beg; beg != e; ++beg) {
825 source.precede(task);
826 task.precede(target);
834 target.work([&result, bop, g_results=make_moc(
std::move(g_results)), w=
id] () {
835 for(
auto i=0u; i<w; i++) {
844 template <
typename L>
845 void FlowBuilder::_linearize(L& keys) {
847 auto itr = keys.begin();
848 auto end = keys.end();
856 for(++nxt; nxt != end; ++nxt, ++itr) {
857 itr->_node->_precede(nxt->_node);
872 template <
typename I,
typename T,
typename B>
879 size_t g =
std::max((d + w - 1) / w,
size_t{2});
885 auto g_results = std::make_unique<T[]>(w);
901 auto task =
emplace([beg, e, op, res = &g_results[
id]] ()
mutable {
903 for(++beg; beg != e; ++beg) {
912 source.precede(task);
913 task.precede(target);
927 target.work([g_results=make_moc(
std::move(g_results)), &result, op, w=
id] () {
928 for(
auto i=0u; i<w; i++) {
929 result = op(
std::move(result), g_results.object[i]);
942 template <
typename C>
944 _node->_handle.emplace<Node::StaticWork>(std::forward<C>(c));
950 template <
typename C>
952 _node->_handle.emplace<Node::DynamicWork>(
953 [c=std::forward<C>(c)] (
Subflow& fb)
mutable {
955 if(fb._graph.empty()) {
964 template <
typename C>
966 _node->_handle.emplace<Node::ConditionWork>(std::forward<C>(c));
void linearize(std::vector< Task > &tasks)
adds adjacent dependency links to a linear list of tasks
Definition: flow_builder.hpp:862
void broadcast(Task A, std::vector< Task > &others)
adds dependency links from one task A to many tasks
Definition: flow_builder.hpp:497
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:735
Definition: taskflow.hpp:5
T hardware_concurrency(T... args)
std::enable_if_t< is_static_task_v< C >, Task > & work(C &&callable)
assigns a static task
Definition: flow_builder.hpp:943
Task placeholder()
creates an empty task
Definition: flow_builder.hpp:525
Subflow(Args &&... args)
constructs a subflow builder object
Definition: flow_builder.hpp:381
void detach()
enables the subflow to detach from its parent task
Definition: flow_builder.hpp:391
bool detached() const
queries if the subflow will be detached from its parent task
Definition: flow_builder.hpp:396
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:727
Task & succeed(Ts &&... tasks)
adds precedence links from other tasks to this
Definition: task.hpp:274
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:418
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:532
Task composed_of(Taskflow &taskflow)
creates a module task from a taskflow
Definition: flow_builder.hpp:484
void precede(Task A, Task B)
adds a dependency link from task A to task B
Definition: flow_builder.hpp:492
the class to create a task dependency graph
Definition: core/taskflow.hpp:18
void gather(std::vector< Task > &others, Task A)
adds dependency links from many tasks to one task A
Definition: flow_builder.hpp:511
FlowBuilder(Graph &graph)
construct a flow builder object
Definition: flow_builder.hpp:333
Building blocks 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:401
task handle to a node in a task dependency graph
Definition: task.hpp:51
Task & precede(Ts &&... tasks)
adds precedence links from this to other tasks
Definition: task.hpp:253
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:873
The building blocks of dynamic tasking.
Definition: flow_builder.hpp:344
void join()
enables the subflow to join its parent task
Definition: flow_builder.hpp:386
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:718