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

class to create a taskflow object More...

#include <taskflow.hpp>

Inheritance diagram for tf::Taskflow:
Collaboration diagram for tf::Taskflow:

Public Member Functions

 Taskflow (const std::string &name)
 constructs a taskflow with the given name
 
 Taskflow ()
 constructs a taskflow
 
 Taskflow (Taskflow &&rhs)
 constructs a taskflow from a moved taskflow
 
Taskflowoperator= (Taskflow &&rhs)
 move assignment operator
 
 ~Taskflow ()=default
 default destructor
 
void dump (std::ostream &ostream) const
 dumps the taskflow to a DOT format through a std::ostream target
 
std::string dump () const
 dumps the taskflow to a std::string of DOT format
 
size_t num_tasks () const
 queries the number of tasks
 
bool empty () const
 queries the emptiness of the taskflow
 
void name (const std::string &)
 assigns a name to the taskflow
 
const std::stringname () const
 queries the name of the taskflow
 
void clear ()
 clears the associated task dependency graph
 
template<typename V >
void for_each_task (V &&visitor) const
 applies a visitor to each task in the taskflow
 
Graphgraph ()
 returns a reference to the underlying graph object
 
- Public Member Functions inherited from tf::FlowBuilder
 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
 

Friends

class Topology
 
class Executor
 
class FlowBuilder
 

Additional Inherited Members

- Protected Attributes inherited from tf::FlowBuilder
Graph_graph
 associated graph object
 

Detailed Description

class to create a taskflow object

A taskflow manages a task dependency graph where each task represents a callable object (e.g., lambda, std::function) and an edge represents a dependency between two tasks. A task is one of the following types:

  1. static task : the callable constructible from std::function<void()>
  2. dynamic task : the callable constructible from std::function<void(tf::Subflow&)>
  3. condition task : the callable constructible from std::function<int()>
  4. multi-condition task: the callable constructible from std::function<tf::SmallVector<int>()>
  5. module task : the task constructed from tf::Taskflow::composed_of
  6. runtime task : the callable constructible from std::function<void(tf::Runtime&)>
  7. cudaFlow task : the callable constructible from std::function<void(tf::cudaFlow&)> or std::function<void(tf::cudaFlowCapturer&)>
  8. syclFlow task : the callable constructible from std::function<void(tf::syclFlow&)>

Each task is a basic computation unit and is run by one worker thread from an executor. The following example creates a simple taskflow graph of four static tasks, A, B, C, and D, where A runs before B and C and D runs after B and C.

tf::Executor executor;
tf::Taskflow taskflow("simple");
tf::Task A = taskflow.emplace([](){ std::cout << "TaskA\n"; });
tf::Task B = taskflow.emplace([](){ std::cout << "TaskB\n"; });
tf::Task C = taskflow.emplace([](){ std::cout << "TaskC\n"; });
tf::Task D = taskflow.emplace([](){ std::cout << "TaskD\n"; });
A.precede(B, C); // A runs before B and C
D.succeed(B, C); // D runs after B and C
executor.run(taskflow).wait();
class to create an executor for running a taskflow graph
Definition executor.hpp:50
tf::Future< void > run(Taskflow &taskflow)
runs a taskflow once
Definition executor.hpp:1573
class to create a task handle over a node in a taskflow graph
Definition task.hpp:187
Task & succeed(Ts &&... tasks)
adds precedence links from other tasks to this
Definition task.hpp:428
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 itself is NOT thread-safe. You should not modifying the graph while it is running, such as adding new tasks, adding new dependencies, and moving the taskflow to another. To minimize the overhead of task creation, our runtime leverages a global object pool to recycle tasks in a thread-safe manner.

Please refer to Cookbook to learn more about each task type and how to submit a taskflow to an executor.

Constructor & Destructor Documentation

◆ Taskflow() [1/2]

tf::Taskflow::Taskflow ( const std::string name)
inline

constructs a taskflow with the given name

tf::Taskflow taskflow("My Taskflow");
std::cout << taskflow.name(); // "My Taskflow"

◆ Taskflow() [2/2]

tf::Taskflow::Taskflow ( Taskflow &&  rhs)
inline

constructs a taskflow from a moved taskflow

Constructing a taskflow taskflow1 from a moved taskflow taskflow2 will migrate the graph of taskflow2 to taskflow1. After the move, taskflow2 will become empty.

tf::Taskflow taskflow1(std::move(taskflow2));
assert(taskflow2.empty());
T move(T... args)

Notice that taskflow2 should not be running in an executor during the move operation, or the behavior is undefined.

◆ ~Taskflow()

tf::Taskflow::~Taskflow ( )
default

default destructor

When the destructor is called, all tasks and their associated data (e.g., captured data) will be destroyed. It is your responsibility to ensure all submitted execution of this taskflow have completed before destroying it. For instance, the following code results in undefined behavior since the executor may still be running the taskflow while it is destroyed after the block.

{
tf::Taskflow taskflow;
executor.run(taskflow);
}

To fix the problem, we must wait for the execution to complete before destroying the taskflow.

{
tf::Taskflow taskflow;
executor.run(taskflow).wait();
}

Member Function Documentation

◆ clear()

void tf::Taskflow::clear ( )
inline

clears the associated task dependency graph

When you clear a taskflow, all tasks and their associated data (e.g., captured data in task callables) will be destroyed. The behavior of clearing a running taskflow is undefined.

◆ dump() [1/2]

std::string tf::Taskflow::dump ( ) const
inline

dumps the taskflow to a std::string of DOT format

This method is similar to tf::Taskflow::dump(std::ostream& ostream), but returning a string of the graph in DOT format.

◆ dump() [2/2]

void tf::Taskflow::dump ( std::ostream ostream) const
inline

dumps the taskflow to a DOT format through a std::ostream target

taskflow.dump(std::cout); // dump the graph to the standard output
std::ofstream ofs("output.dot");
taskflow.dump(ofs); // dump the graph to the file output.dot

For dynamically spawned tasks, such as module tasks, subflow tasks, and GPU tasks, you need to run the taskflow first before you can dump the entire graph.

tf::Task parent = taskflow.emplace([](tf::Subflow sf){
sf.emplace([](){ std::cout << "child\n"; });
});
taskflow.dump(std::cout); // this dumps only the parent tasks
executor.run(taskflow).wait();
taskflow.dump(std::cout); // this dumps both parent and child tasks
Task emplace(C &&callable)
creates a static task
Definition flow_builder.hpp:742
class to construct a subflow graph from the execution of a dynamic task
Definition flow_builder.hpp:889
void dump(std::ostream &ostream) const
dumps the task through an output stream
Definition task.hpp:573

◆ empty()

bool tf::Taskflow::empty ( ) const
inline

queries the emptiness of the taskflow

An empty taskflow has no tasks. That is the return of tf::Taskflow::num_tasks is zero.

◆ for_each_task()

template<typename V >
void tf::Taskflow::for_each_task ( V &&  visitor) const

applies a visitor to each task in the taskflow

A visitor is a callable that takes an argument of type tf::Task and returns nothing. The following example iterates each task in a taskflow and prints its name:

taskflow.for_each_task([](tf::Task task){
std::cout << task.name() << '\n';
});
const std::string & name() const
queries the name of the task
Definition task.hpp:499

◆ graph()

Graph & tf::Taskflow::graph ( )
inline

returns a reference to the underlying graph object

A graph object (of type tf::Graph) is the ultimate storage for the task dependency graph and should only be used as an opaque data structure to interact with the executor (e.g., composition).

◆ name() [1/2]

const std::string & tf::Taskflow::name ( ) const
inline

queries the name of the taskflow

std::cout << "my name is: " << taskflow.name();

◆ name() [2/2]

void tf::Taskflow::name ( const std::string name)
inline

assigns a name to the taskflow

taskflow.name("assign another name");

◆ operator=()

Taskflow & tf::Taskflow::operator= ( Taskflow &&  rhs)
inline

move assignment operator

Moving a taskflow taskflow2 to another taskflow taskflow1 will destroy the existing graph of taskflow1 and assign it the graph of taskflow2. After the move, taskflow2 will become empty.

taskflow1 = std::move(taskflow2);
assert(taskflow2.empty());

Notice that both taskflow1 and taskflow2 should not be running in an executor during the move operation, or the behavior is undefined.


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