Taskflow  3.2.0-Master-Branch
Loading...
Searching...
No Matches
tf::FlowBuilder Class Reference

class to build a task dependency graph More...

#include <flow_builder.hpp>

Inheritance diagram for tf::FlowBuilder:
Collaboration diagram for tf::FlowBuilder:

Public Member Functions

 FlowBuilder (Graph &graph)
 constructs a flow builder with a graph
 
template<typename C , std::enable_if_t< is_static_task_v< C >, void > * = nullptr>
Task emplace (C &&callable)
 creates a static task
 
template<typename C , std::enable_if_t< is_dynamic_task_v< C >, void > * = nullptr>
Task emplace (C &&callable)
 creates a dynamic task
 
template<typename C , std::enable_if_t< is_condition_task_v< C >, void > * = nullptr>
Task emplace (C &&callable)
 creates a condition task
 
template<typename C , std::enable_if_t< is_multi_condition_task_v< C >, void > * = nullptr>
Task emplace (C &&callable)
 creates a multi-condition task
 
template<typename... C, std::enable_if_t<(sizeof...(C)>1), void > * = nullptr>
auto emplace (C &&... callables)
 creates multiple tasks from a list of callable objects
 
void erase (Task task)
 removes a task from a taskflow
 
template<typename T >
Task composed_of (T &object)
 creates a module task for the target object
 
Task placeholder ()
 creates a placeholder task
 
template<typename C , std::enable_if_t< is_cudaflow_task_v< C >, void > * = nullptr>
Task emplace (C &&callable)
 creates a cudaFlow task on the caller's GPU device context
 
template<typename C , typename D , std::enable_if_t< is_cudaflow_task_v< C >, void > * = nullptr>
Task emplace_on (C &&callable, D &&device)
 creates a cudaFlow task on the given device
 
template<typename C , std::enable_if_t< is_syclflow_task_v< C >, void > * = nullptr>
Task emplace (C &&callable)
 creates a syclFlow task on the default queue
 
template<typename C , typename Q , std::enable_if_t< is_syclflow_task_v< C >, void > * = nullptr>
Task emplace_on (C &&callable, Q &&queue)
 creates a syclFlow task on the given queue
 
template<typename C , std::enable_if_t< is_runtime_task_v< C >, void > * = nullptr>
Task emplace (C &&callable)
 creates a runtime task
 
void linearize (std::vector< Task > &tasks)
 adds adjacent dependency links to a linear list of tasks
 
void linearize (std::initializer_list< Task > tasks)
 adds adjacent dependency links to a linear list of tasks
 
template<typename B , typename E , typename C >
Task for_each (B first, E last, C callable)
 constructs a STL-styled parallel-for task
 
template<typename B , typename E , typename S , typename C >
Task for_each_index (B first, E last, S step, C callable)
 constructs a parallel-transform task
 
template<typename B , typename E , typename O , typename C >
Task transform (B first1, E last1, O d_first, C c)
 constructs a parallel-transform task
 
template<typename B1 , typename E1 , typename B2 , typename O , typename C >
Task transform (B1 first1, E1 last1, B2 first2, O d_first, C c)
 constructs a parallel-transform task
 
template<typename B , typename E , typename T , typename O >
Task reduce (B first, E last, T &init, O bop)
 constructs a STL-styled parallel-reduce task
 
template<typename B , typename E , typename T , typename BOP , typename UOP >
Task transform_reduce (B first, E last, T &init, BOP bop, UOP uop)
 constructs a STL-styled parallel transform-reduce task
 
template<typename B , typename E , typename C >
Task sort (B first, E last, C cmp)
 constructs a dynamic task to perform STL-styled parallel sort
 
template<typename B , typename E >
Task sort (B first, E last)
 constructs a dynamic task to perform STL-styled parallel sort using the std::less<T> comparator, where T is the element type
 

Protected Attributes

Graph_graph
 associated graph object
 

Friends

class Executor
 

Detailed Description

class to build a task dependency graph

The class provides essential methods to construct a task dependency graph from which tf::Taskflow and tf::Subflow are derived.

Member Function Documentation

◆ composed_of()

template<typename T >
Task tf::FlowBuilder::composed_of ( T &  object)

creates a module task for the target object

Template Parameters
Ttarget object type
Parameters
objecta custom object that defines the method T::graph()
Returns
a tf::Task handle

The example below demonstrates a taskflow composition using the composed_of method.

tf::Taskflow t1, t2;
t1.emplace([](){ std::cout << "t1"; });
// t2 is partially composed of t1
tf::Task comp = t2.composed_of(t1);
tf::Task init = t2.emplace([](){ std::cout << "t2"; });
init.precede(comp);
Task emplace(C &&callable)
creates a static task
Definition flow_builder.hpp:742
Task composed_of(T &object)
creates a module task for the target object
Definition flow_builder.hpp:812
class to create a task handle over a node in a taskflow graph
Definition task.hpp:187
Task & precede(Ts &&... tasks)
adds precedence links from this to other tasks
Definition task.hpp:420
class to create a taskflow object
Definition core/taskflow.hpp:73

The taskflow object t2 is composed of another taskflow object t1, preceded by another static task init. When taskflow t2 is submitted to an executor, init will run first and then comp which spwans its definition in taskflow t1.

The target object being composed must define the method T::graph() that returns a reference to a graph object of type tf::Graph such that it can interact with the executor. For example:

// custom struct
struct MyObj {
tf::Graph graph;
MyObj() {
tf::FlowBuilder builder(graph);
tf::Task task = builder.emplace([](){
std::cout << "a task\n"; // static task
});
}
Graph& graph() { return graph; }
};
MyObj obj;
tf::Task comp = taskflow.composed_of(obj);
class to build a task dependency graph
Definition flow_builder.hpp:21
class to create a graph object
Definition graph.hpp:56
Task & composed_of(T &object)
creates a module task from a taskflow
Definition task.hpp:436

Please refer to Composable Tasking for details.

◆ emplace() [1/8]

template<typename... C, std::enable_if_t<(sizeof...(C)>1), void > * >
auto tf::FlowBuilder::emplace ( C &&...  callables)

creates multiple tasks from a list of callable objects

Template Parameters
Ccallable types
Parameters
callablesone or multiple callable objects constructible from each task category
Returns
a tf::Task handle

The method returns a tuple of tasks each corresponding to the given callable target. You can use structured binding to get the return tasks one by one. The following example creates four static tasks and assign them to A, B, C, and D using structured binding.

auto [A, B, C, D] = taskflow.emplace(
[] () { std::cout << "A"; },
[] () { std::cout << "B"; },
[] () { std::cout << "C"; },
[] () { std::cout << "D"; }
);

◆ emplace() [2/8]

template<typename C , std::enable_if_t< is_syclflow_task_v< C >, void > * >
Task tf::FlowBuilder::emplace ( C &&  callable)

creates a static task

Template Parameters
Ccallable type constructible from std::function<void()>
Parameters
callablecallable to construct a static task
Returns
a tf::Task handle

The following example creates a static task.

tf::Task static_task = taskflow.emplace([](){});

Please refer to Static Tasking for details.

◆ emplace() [3/8]

template<typename C , std::enable_if_t< is_dynamic_task_v< C >, void > * = nullptr>
Task tf::FlowBuilder::emplace ( C &&  callable)

creates a dynamic task

Template Parameters
Ccallable type constructible from std::function<void(tf::Subflow&)>
Parameters
callablecallable to construct a dynamic task
Returns
a tf::Task handle

The following example creates a dynamic task (tf::Subflow) that spawns two static tasks.

tf::Task dynamic_task = taskflow.emplace([](tf::Subflow& sf){
tf::Task static_task1 = sf.emplace([](){});
tf::Task static_task2 = sf.emplace([](){});
});
class to construct a subflow graph from the execution of a dynamic task
Definition flow_builder.hpp:889

Please refer to Dynamic Tasking for details.

◆ emplace() [4/8]

template<typename C , std::enable_if_t< is_condition_task_v< C >, void > * = nullptr>
Task tf::FlowBuilder::emplace ( C &&  callable)

creates a condition task

Template Parameters
Ccallable type constructible from std::function<int()>
Parameters
callablecallable to construct a condition task
Returns
a tf::Task handle

The following example creates an if-else block using one condition task and three static tasks.

tf::Taskflow taskflow;
auto [init, cond, yes, no] = taskflow.emplace(
[] () { },
[] () { return 0; },
[] () { std::cout << "yes\n"; },
[] () { std::cout << "no\n"; }
);
// executes yes if cond returns 0, or no if cond returns 1
cond.precede(yes, no);
cond.succeed(init);
Task & succeed(Ts &&... tasks)
adds precedence links from other tasks to this
Definition task.hpp:428

Please refer to Conditional Tasking for details.

◆ emplace() [5/8]

template<typename C , std::enable_if_t< is_multi_condition_task_v< C >, void > * = nullptr>
Task tf::FlowBuilder::emplace ( C &&  callable)

creates a multi-condition task

Template Parameters
Ccallable type constructible from std::function<tf::SmallVector<int>()>
Parameters
callablecallable to construct a multi-condition task
Returns
a tf::Task handle

The following example creates a multi-condition task that selectively jumps to two successor tasks.

tf::Taskflow taskflow;
auto [init, cond, branch1, branch2, branch3] = taskflow.emplace(
[] () { },
[] () { return tf::SmallVector{0, 2}; },
[] () { std::cout << "branch1\n"; },
[] () { std::cout << "branch2\n"; },
[] () { std::cout << "branch3\n"; }
);
// executes branch1 and branch3 when cond returns 0 and 2
cond.precede(branch1, branch2, branch3);
cond.succeed(init);
class to define a vector optimized for small array
Definition small_vector.hpp:918

Please refer to Conditional Tasking for details.

◆ emplace() [6/8]

template<typename C , std::enable_if_t< is_cudaflow_task_v< C >, void > * = nullptr>
Task tf::FlowBuilder::emplace ( C &&  callable)

creates a cudaFlow task on the caller's GPU device context

Template Parameters
Ccallable type constructible from std::function<void(tf::cudaFlow&)>
Returns
a tf::Task handle

This method is equivalent to calling tf::FlowBuilder::emplace_on(callable, d) where d is the caller's device context. The following example creates a cudaFlow of two kernel tasks, task1 and task2, where task1 runs before task2.

taskflow.emplace([&](tf::cudaFlow& cf){
// create two kernel tasks
tf::cudaTask task1 = cf.kernel(grid1, block1, shm1, kernel1, args1);
tf::cudaTask task2 = cf.kernel(grid2, block2, shm2, kernel2, args2);
// kernel1 runs before kernel2
task1.precede(task2);
});
class to create a cudaFlow task dependency graph
Definition cudaflow.hpp:56
cudaTask kernel(dim3 g, dim3 b, size_t s, F f, ArgsT &&... args)
creates a kernel task
Definition cudaflow.hpp:1272
class to create a task handle over an internal node of a cudaFlow graph
Definition cuda_task.hpp:65
cudaTask & precede(Ts &&... tasks)
adds precedence links from this to other tasks
Definition cuda_task.hpp:182

Please refer to GPU Tasking (cudaFlow) and GPU Tasking (cudaFlowCapturer) for details.

◆ emplace() [7/8]

template<typename C , std::enable_if_t< is_syclflow_task_v< C >, void > * = nullptr>
Task tf::FlowBuilder::emplace ( C &&  callable)

creates a syclFlow task on the default queue

Template Parameters
Ccallable type constructible from std::function<void(tf::syclFlow&)>
Parameters
callablea callable that takes a referenced tf::syclFlow object
Returns
a tf::Task handle

The following example creates a syclFlow on the default queue to submit two kernel tasks, task1 and task2, where task1 runs before task2.

taskflow.emplace([&](tf::syclFlow& cf){
// create two single-thread kernel tasks
tf::syclTask task1 = cf.single_task([](){});
tf::syclTask task2 = cf.single_task([](){});
// kernel1 runs before kernel2
task1.precede(task2);
});
class for building a SYCL task dependency graph
Definition syclflow.hpp:23
syclTask single_task(F &&func)
invokes a SYCL kernel function using only one thread
Definition syclflow.hpp:492
handle to a node of the internal CUDA graph
Definition sycl_task.hpp:21
syclTask & precede(Ts &&... tasks)
adds precedence links from this to other tasks
Definition sycl_task.hpp:131

◆ emplace() [8/8]

template<typename C , std::enable_if_t< is_runtime_task_v< C >, void > * = nullptr>
Task tf::FlowBuilder::emplace ( C &&  callable)

creates a runtime task

Template Parameters
Ccallable type constructible from std::function<void(tf::Runtime&)>
Parameters
callablecallable to construct a runtime task
Returns
a tf::Task handle

The following example creates a runtime task that enables in-task control over the running executor.

tf::Task runtime_task = taskflow.emplace([](tf::Runtime& rt){
auto& executor = rt.executor();
std::cout << executor.num_workers() << '\n';
});
class to create a runtime object used by a runtime task
Definition graph.hpp:150
Executor & executor()
obtains the running executor
Definition graph.hpp:233

Please refer to Runtime Tasking for details.

◆ emplace_on() [1/2]

template<typename C , typename D , std::enable_if_t< is_cudaflow_task_v< C >, void > * >
Task tf::FlowBuilder::emplace_on ( C &&  callable,
D &&  device 
)

creates a cudaFlow task on the given device

Template Parameters
Ccallable type constructible from std::function<void(tf::cudaFlow&)>
Ddevice type, either int or std::ref<int> (stateful)
Returns
a tf::Task handle

The following example creates a cudaFlow of two kernel tasks, task1 and task2 on GPU 2, where task1 runs before task2

taskflow.emplace_on([&](tf::cudaFlow& cf){
// create two kernel tasks
tf::cudaTask task1 = cf.kernel(grid1, block1, shm1, kernel1, args1);
tf::cudaTask task2 = cf.kernel(grid2, block2, shm2, kernel2, args2);
// kernel1 runs before kernel2
task1.precede(task2);
}, 2);

◆ emplace_on() [2/2]

template<typename C , typename Q , std::enable_if_t< is_syclflow_task_v< C >, void > * >
Task tf::FlowBuilder::emplace_on ( C &&  callable,
Q &&  queue 
)

creates a syclFlow task on the given queue

Template Parameters
Ccallable type constructible from std::function<void(tf::syclFlow&)>
Qqueue type
Parameters
callablea callable that takes a referenced tf::syclFlow object
queuea queue of type sycl::queue
Returns
a tf::Task handle

The following example creates a syclFlow on the given queue to submit two kernel tasks, task1 and task2, where task1 runs before task2.

taskflow.emplace_on([&](tf::syclFlow& cf){
// create two single-thread kernel tasks
tf::syclTask task1 = cf.single_task([](){});
tf::syclTask task2 = cf.single_task([](){});
// kernel1 runs before kernel2
task1.precede(task2);
}, queue);

◆ erase()

void tf::FlowBuilder::erase ( Task  task)
inline

removes a task from a taskflow

Parameters
tasktask to remove

Removes a task and its input and output dependencies from the graph associated with the flow builder. If the task does not belong to the graph, nothing will happen.

tf::Task A = taskflow.emplace([](){ std::cout << "A"; });
tf::Task B = taskflow.emplace([](){ std::cout << "B"; });
tf::Task C = taskflow.emplace([](){ std::cout << "C"; });
tf::Task D = taskflow.emplace([](){ std::cout << "D"; });
A.precede(B, C, D);
// erase A from the taskflow and its dependencies to B, C, and D
taskflow.erase(A);

◆ for_each()

template<typename B , typename E , typename C >
Task tf::FlowBuilder::for_each ( first,
last,
callable 
)

constructs a STL-styled parallel-for task

Template Parameters
Bbeginning iterator type
Eending iterator type
Ccallable type
Parameters
firstiterator to the beginning (inclusive)
lastiterator to the end (exclusive)
callablea callable object to apply to the dereferenced iterator
Returns
a tf::Task handle

The task spawns a subflow that applies the callable object to each object obtained by dereferencing every iterator in the range [first, last). This method is equivalent to the parallel execution of the following loop:

for(auto itr=first; itr!=last; itr++) {
callable(*itr);
}

Arguments templated to enable stateful range using std::reference_wrapper. The callable needs to take a single argument of the dereferenced iterator type.

Please refer to Parallel Iterations for details.

◆ for_each_index()

template<typename B , typename E , typename S , typename C >
Task tf::FlowBuilder::for_each_index ( first,
last,
step,
callable 
)

constructs a parallel-transform task

Template Parameters
Bbeginning index type (must be integral)
Eending index type (must be integral)
Sstep type (must be integral)
Ccallable type
Parameters
firstindex of the beginning (inclusive)
lastindex of the end (exclusive)
stepstep size
callablea callable object to apply to each valid index
Returns
a tf::Task handle

The task spawns a subflow that applies the callable object to each index in the range [first, last) with the step size. This method is equivalent to the parallel execution of the following loop:

// case 1: step size is positive
for(auto i=first; i<last; i+=step) {
callable(i);
}
// case 2: step size is negative
for(auto i=first, i>last; i+=step) {
callable(i);
}

Arguments are templated to enable stateful range using std::reference_wrapper. The callable needs to take a single argument of the integral index type.

Please refer to Parallel Iterations for details.

◆ linearize() [1/2]

void tf::FlowBuilder::linearize ( std::initializer_list< Task tasks)
inline

adds adjacent dependency links to a linear list of tasks

Parameters
tasksan initializer list of tasks

This member function creates linear dependencies over a list of tasks.

tf::Task A = taskflow.emplace([](){ std::cout << "A"; });
tf::Task B = taskflow.emplace([](){ std::cout << "B"; });
tf::Task C = taskflow.emplace([](){ std::cout << "C"; });
tf::Task D = taskflow.emplace([](){ std::cout << "D"; });
taskflow.linearize({A, B, C, D}); // A->B->C->D

◆ linearize() [2/2]

void tf::FlowBuilder::linearize ( std::vector< Task > &  tasks)
inline

adds adjacent dependency links to a linear list of tasks

Parameters
tasksa vector of tasks

This member function creates linear dependencies over a vector of tasks.

tf::Task A = taskflow.emplace([](){ std::cout << "A"; });
tf::Task B = taskflow.emplace([](){ std::cout << "B"; });
tf::Task C = taskflow.emplace([](){ std::cout << "C"; });
tf::Task D = taskflow.emplace([](){ std::cout << "D"; });
std::vector<tf::Task> tasks {A, B, C, D}
taskflow.linearize(tasks); // A->B->C->D

◆ placeholder()

Task tf::FlowBuilder::placeholder ( )
inline

creates a placeholder task

Returns
a tf::Task handle

A placeholder task maps to a node in the taskflow graph, but it does not have any callable work assigned yet. A placeholder task is different from an empty task handle that does not point to any node in a graph.

// create a placeholder task with no callable target assigned
tf::Task placeholder = taskflow.placeholder();
assert(placeholder.empty() == false && placeholder.has_work() == false);
// create an empty task handle
tf::Task task;
assert(task.empty() == true);
// assign the task handle to the placeholder task
task = placeholder;
assert(task.empty() == false && task.has_work() == false);
Task placeholder()
creates a placeholder task
Definition flow_builder.hpp:820
bool empty() const
queries if the task handle points to a task node
Definition task.hpp:524
bool has_work() const
queries if the task has a work assigned
Definition task.hpp:529

◆ reduce()

template<typename B , typename E , typename T , typename O >
Task tf::FlowBuilder::reduce ( first,
last,
T &  init,
bop 
)

constructs a STL-styled parallel-reduce task

Template Parameters
Bbeginning iterator type
Eending iterator type
Tresult type
Obinary reducer type
Parameters
firstiterator to the beginning (inclusive)
lastiterator to the end (exclusive)
initinitial value of the reduction and the storage for the reduced result
bopbinary operator that will be applied
Returns
a tf::Task handle

The task spawns a subflow to perform parallel reduction over init and the elements in the range [first, last). The reduced result is store in init. This method is equivalent to the parallel execution of the following loop:

for(auto itr=first; itr!=last; itr++) {
init = bop(init, *itr);
}

Arguments are templated to enable stateful range using std::reference_wrapper.

Please refer to Parallel Reduction for details.

◆ sort() [1/2]

template<typename B , typename E >
Task tf::FlowBuilder::sort ( first,
last 
)

constructs a dynamic task to perform STL-styled parallel sort using the std::less<T> comparator, where T is the element type

Template Parameters
Bbeginning iterator type (random-accessible)
Eending iterator type (random-accessible)
Parameters
firstiterator to the beginning (inclusive)
lastiterator to the end (exclusive)

The task spawns a subflow to parallelly sort elements in the range [first, last) using the std::less<T> comparator, where T is the dereferenced iterator type.

Arguments are templated to enable stateful range using std::reference_wrapper.

Please refer to Parallel Sort for details.

◆ sort() [2/2]

template<typename B , typename E , typename C >
Task tf::FlowBuilder::sort ( first,
last,
cmp 
)

constructs a dynamic task to perform STL-styled parallel sort

Template Parameters
Bbeginning iterator type (random-accessible)
Eending iterator type (random-accessible)
Ccomparator type
Parameters
firstiterator to the beginning (inclusive)
lastiterator to the end (exclusive)
cmpcomparison function object

The task spawns a subflow to parallelly sort elements in the range [first, last).

Arguments are templated to enable stateful range using std::reference_wrapper.

Please refer to Parallel Sort for details.

◆ transform() [1/2]

template<typename B , typename E , typename O , typename C >
Task tf::FlowBuilder::transform ( first1,
last1,
d_first,
c 
)

constructs a parallel-transform task

Template Parameters
Bbeginning input iterator type
Eending input iterator type
Ooutput iterator type
Ccallable type
Parameters
first1iterator to the beginning of the first range
last1iterator to the end of the first range
d_firstiterator to the beginning of the output range
can unary callable to apply to dereferenced input elements
Returns
a tf::Task handle

The task spawns a subflow that applies the callable object to an input range and stores the result in another output range. This method is equivalent to the parallel execution of the following loop:

while (first1 != last1) {
*d_first++ = c(*first1++);
}

Arguments are templated to enable stateful range using std::reference_wrapper. The callable needs to take a single argument of the dereferenced iterator type.

◆ transform() [2/2]

template<typename B1 , typename E1 , typename B2 , typename O , typename C >
Task tf::FlowBuilder::transform ( B1  first1,
E1  last1,
B2  first2,
d_first,
c 
)

constructs a parallel-transform task

Template Parameters
B1beginning input iterator type for the first input range
E1ending input iterator type for the first input range
B2beginning input iterator type for the first second range
Ooutput iterator type
Ccallable type
Parameters
first1iterator to the beginning of the first input range
last1iterator to the end of the first input range
first2iterator to the beginning of the second input range
d_firstiterator to the beginning of the output range
ca binary operator to apply to dereferenced input elements
Returns
a tf::Task handle

The task spawns a subflow that applies the callable object to two input ranges and stores the result in another output range. This method is equivalent to the parallel execution of the following loop:

while (first1 != last1) {
*d_first++ = c(*first1++, *first2++);
}

Arguments are templated to enable stateful range using std::reference_wrapper. The callable needs to take two arguments of dereferenced elements from the two input ranges.

◆ transform_reduce()

template<typename B , typename E , typename T , typename BOP , typename UOP >
Task tf::FlowBuilder::transform_reduce ( first,
last,
T &  init,
BOP  bop,
UOP  uop 
)

constructs a STL-styled parallel transform-reduce task

Template Parameters
Bbeginning iterator type
Eending iterator type
Tresult type
BOPbinary reducer type
UOPunary transformion type
Parameters
firstiterator to the beginning (inclusive)
lastiterator to the end (exclusive)
initinitial value of the reduction and the storage for the reduced result
bopbinary operator that will be applied in unspecified order to the results of uop
uopunary operator that will be applied to transform each element in the range to the result type
Returns
a tf::Task handle

The task spawns a subflow to perform parallel reduction over init and the transformed elements in the range [first, last). The reduced result is store in init. This method is equivalent to the parallel execution of the following loop:

for(auto itr=first; itr!=last; itr++) {
init = bop(init, uop(*itr));
}

Arguments are templated to enable stateful range using std::reference_wrapper.

Please refer to Parallel Reduction for details.


The documentation for this class was generated from the following files: