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>
113 template <
typename I,
typename C>
136 std::enable_if_t<std::is_integral<std::decay_t<I>>::value,
void>* =
nullptr 139 I beg, I end, I step, C&& callable,
size_t chunk = 1
162 std::enable_if_t<std::is_floating_point<std::decay_t<I>>::value,
void>* =
nullptr 165 I beg, I end, I step, C&& callable,
size_t chunk = 1
185 template <
typename I,
typename T,
typename B>
203 template <
typename I,
typename T>
221 template <
typename I,
typename T>
245 template <
typename I,
typename T,
typename B,
typename U>
272 template <
typename I,
typename T,
typename B,
typename P,
typename U>
274 I beg, I end, T& result, B&& bop1, P&& bop2, U&& uop
342 template <
typename L>
352 template <
typename... C, std::enable_if_t<(
sizeof...(C)>1),
void>*>
354 return std::make_tuple(
emplace(std::forward<C>(cs))...);
359 template <
typename C>
361 auto n = _graph.emplace_back(
362 nstd::in_place_type_t<Node::StaticWork>{}, std::forward<C>(c)
369 template <
typename C>
371 auto n = _graph.emplace_back(
372 nstd::in_place_type_t<Node::DynamicWork>{}, std::forward<C>(c)
379 template <
typename C>
381 auto n = _graph.emplace_back(
382 nstd::in_place_type_t<Node::ConditionWork>{}, std::forward<C>(c)
387 #ifdef TF_ENABLE_CUDA 390 template <
typename C>
392 auto n = _graph.emplace_back(
393 nstd::in_place_type_t<Node::cudaFlowWork>{}, std::forward<C>(c)
401 auto node = _graph.emplace_back(
402 nstd::in_place_type_t<Node::ModuleWork>{}, &taskflow
409 from._node->_precede(to._node);
428 for(
auto from : froms) {
435 for(
auto from : froms) {
442 auto node = _graph.emplace_back();
447 template <
typename I,
typename C>
449 I beg, I end, C&& c,
size_t chunk
462 size_t remain = std::distance(beg, end);
468 auto x = std::min(remain, chunk);
473 auto task =
emplace([beg, e, c] ()
mutable {
474 std::for_each(beg, e, c);
485 if(S.num_successors() == 0) {
489 return std::make_pair(S, T);
496 std::enable_if_t<std::is_integral<std::decay_t<I>>::value,
void>*
500 if((s == 0) || (beg < end && s <= 0) || (beg > end && s >=0) ) {
501 TF_THROW(
"invalid range [", beg,
", ", end,
") with step size ", s);
515 auto o =
static_cast<I
>(chunk) * s;
516 auto e = std::min(beg + o, end);
517 auto task =
emplace([=] ()
mutable {
518 for(
auto i=beg; i<e; i+=s) {
522 source.precede(task);
523 task.precede(target);
530 auto o =
static_cast<I
>(chunk) * s;
531 auto e = std::max(beg + o, end);
532 auto task =
emplace([=] ()
mutable {
533 for(
auto i=beg; i>e; i+=s) {
537 source.precede(task);
538 task.precede(target);
543 if(source.num_successors() == 0) {
544 source.precede(target);
547 return std::make_pair(source, target);
551 template <
typename I,
typename C,
552 std::enable_if_t<std::is_floating_point<std::decay_t<I>>::value,
void>*
556 if((s == 0) || (beg < end && s <= 0) || (beg > end && s >=0) ) {
557 TF_THROW(
"invalid range [", beg,
", ", end,
") with step size ", s);
572 for(I e=beg; e<
end; e+=s) {
574 auto task =
emplace([=] ()
mutable {
575 for(
size_t i=0; i<N; ++i, b+=s) {
579 source.precede(task);
580 task.precede(target);
587 auto task =
emplace([=] ()
mutable {
588 for(
size_t i=0; i<N; ++i, b+=s) {
592 source.precede(task);
593 task.precede(target);
599 for(I e=beg; e>
end; e+=s) {
601 auto task =
emplace([=] ()
mutable {
602 for(
size_t i=0; i<N; ++i, b+=s) {
606 source.precede(task);
607 task.precede(target);
614 auto task =
emplace([=] ()
mutable {
615 for(
size_t i=0; i<N; ++i, b+=s) {
619 source.precede(task);
620 task.precede(target);
624 if(source.num_successors() == 0) {
625 source.precede(target);
633 template <
typename I,
typename T>
635 return reduce(beg, end, result, [] (
const auto& l,
const auto& r) {
636 return std::min(l, r);
642 template <
typename I,
typename T>
644 return reduce(beg, end, result, [] (
const auto& l,
const auto& r) {
645 return std::max(l, r);
650 template <
typename I,
typename T,
typename B,
typename U>
652 I beg, I end, T& result, B&& bop, U&& uop
658 size_t d = std::distance(beg, end);
660 size_t g = std::max((d + w - 1) / w,
size_t{2});
666 auto g_results = std::make_unique<T[]>(w);
675 size_t x = std::min(remain, g);
680 auto task =
emplace([beg, e, bop, uop, res=&(g_results[
id])] ()
mutable {
682 for(++beg; beg != e; ++beg) {
683 *res = bop(std::move(*res), uop(*beg));
687 source.precede(task);
688 task.precede(target);
696 target.work([&result, bop, res=make_moc(std::move(g_results)), w=
id] () {
697 for(
auto i=0u; i<w; i++) {
698 result = bop(std::move(result), res.object[i]);
702 return std::make_pair(source, target);
706 template <
typename I,
typename T,
typename B,
typename P,
typename U>
708 I beg, I end, T& result, B&& bop, P&& pop, U&& uop
714 size_t d = std::distance(beg, end);
716 size_t g = std::max((d + w - 1) / w,
size_t{2});
721 auto g_results = std::make_unique<T[]>(w);
730 size_t x = std::min(remain, g);
735 auto task =
emplace([beg, e, uop, pop, res= &g_results[
id]] ()
mutable {
737 for(++beg; beg != e; ++beg) {
738 *res = pop(std::move(*res), *beg);
741 source.precede(task);
742 task.precede(target);
750 target.work([&result, bop, g_results=make_moc(std::move(g_results)), w=
id] () {
751 for(
auto i=0u; i<w; i++) {
752 result = bop(std::move(result), std::move(g_results.object[i]));
756 return std::make_pair(source, target);
760 template <
typename L>
761 void FlowBuilder::_linearize(L& keys) {
763 auto itr = keys.begin();
764 auto end = keys.end();
772 for(++nxt; nxt != end; ++nxt, ++itr) {
773 itr->_node->_precede(nxt->_node);
788 template <
typename I,
typename T,
typename B>
793 size_t d = std::distance(beg, end);
795 size_t g = std::max((d + w - 1) / w,
size_t{2});
801 auto g_results = std::make_unique<T[]>(w);
811 size_t x = std::min(remain, g);
817 auto task =
emplace([beg, e, op, res = &g_results[
id]] ()
mutable {
819 for(++beg; beg != e; ++beg) {
820 *res = op(std::move(*res), *beg);
828 source.precede(task);
829 task.precede(target);
843 target.work([g_results=make_moc(std::move(g_results)), &result, op, w=
id] () {
844 for(
auto i=0u; i<w; i++) {
845 result = op(std::move(result), g_results.object[i]);
849 return std::make_pair(source, target);
867 template <
typename... Args>
892 bool _detached {
false};
896 template <
typename... Args>
void linearize(std::vector< Task > &tasks)
adds adjacent dependency links to a linear list of tasks
Definition: flow_builder.hpp:778
void broadcast(Task A, std::vector< Task > &others)
adds dependency links from one task A to many tasks
Definition: flow_builder.hpp:413
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:651
void succeed(std::vector< Task > &others, Task A)
adds dependency links from many tasks to one task A
Definition: flow_builder.hpp:427
T hardware_concurrency(T... args)
Task placeholder()
creates an empty task
Definition: flow_builder.hpp:441
Subflow(Args &&... args)
constructs a subflow builder object
Definition: flow_builder.hpp:897
void detach()
enables the subflow to detach from its parent task
Definition: flow_builder.hpp:907
bool detached() const
queries if the subflow will be detached from its parent task
Definition: flow_builder.hpp:912
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:643
Task & succeed(Ts &&... tasks)
adds precedence links from other tasks to this
Definition: task.hpp:313
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:360
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:448
Task composed_of(Taskflow &taskflow)
creates a module task from a taskflow
Definition: flow_builder.hpp:400
void precede(Task A, Task B)
adds a dependency link from task A to task B
Definition: flow_builder.hpp:408
main entry to create a task dependency graph
Definition: taskflow.hpp:18
FlowBuilder(Graph &graph)
constructs a flow builder object
Definition: flow_builder.hpp:347
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:917
handle to a node in a task dependency graph
Definition: task.hpp:68
Task & precede(Ts &&... tasks)
adds precedence links from this to other tasks
Definition: task.hpp:290
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:789
building methods of a subflow graph in dynamic tasking
Definition: flow_builder.hpp:860
void join()
enables the subflow to join its parent task
Definition: flow_builder.hpp:902
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:634