Skip to content

Commit 9650dfa

Browse files
updated readme
1 parent 8943914 commit 9650dfa

21 files changed

Lines changed: 1424 additions & 5062 deletions

CMakeLists.txt

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -122,11 +122,11 @@ target_link_libraries(debug ${PROJECT_NAME} Threads::Threads)
122122
add_executable(reduce ${TF_EXAMPLE_DIR}/reduce.cpp)
123123
target_link_libraries(reduce ${PROJECT_NAME} Threads::Threads)
124124

125-
add_executable(threadpool ${TF_EXAMPLE_DIR}/threadpool.cpp)
126-
target_link_libraries(threadpool ${PROJECT_NAME} Threads::Threads)
125+
add_executable(executor_profiler ${TF_EXAMPLE_DIR}/executor_profiler.cpp)
126+
target_link_libraries(executor_profiler ${PROJECT_NAME} Threads::Threads)
127127

128-
add_executable(taskflow ${TF_EXAMPLE_DIR}/taskflow.cpp)
129-
target_link_libraries(taskflow ${PROJECT_NAME} Threads::Threads)
128+
add_executable(taskflow_profiler ${TF_EXAMPLE_DIR}/taskflow_profiler.cpp)
129+
target_link_libraries(taskflow_profiler ${PROJECT_NAME} Threads::Threads)
130130

131131
add_executable(matrix ${TF_EXAMPLE_DIR}/matrix.cpp)
132132
target_link_libraries(matrix ${PROJECT_NAME} Threads::Threads)
@@ -144,9 +144,6 @@ target_link_libraries(multiple_dispatch ${PROJECT_NAME} Threads::Threads)
144144
add_executable(dispatch ${TF_EXAMPLE_DIR}/dispatch.cpp)
145145
target_link_libraries(dispatch ${PROJECT_NAME} Threads::Threads)
146146

147-
add_executable(executor ${TF_EXAMPLE_DIR}/executor.cpp)
148-
target_link_libraries(executor ${PROJECT_NAME} Threads::Threads)
149-
150147
add_executable(dynamic_traversal ${TF_EXAMPLE_DIR}/dynamic_traversal.cpp)
151148
target_link_libraries(dynamic_traversal ${PROJECT_NAME} Threads::Threads)
152149

@@ -203,20 +200,21 @@ add_test(composition-1 ${TF_UTEST_DIR}/taskflow -tc=Composition-1)
203200
add_test(composition-2 ${TF_UTEST_DIR}/taskflow -tc=Composition-2)
204201
add_test(composition-3 ${TF_UTEST_DIR}/taskflow -tc=Composition-3)
205202

206-
# unittest for threadpool
207-
add_executable(threadpool_test_tmp unittest/threadpool.cpp)
208-
target_link_libraries(threadpool_test_tmp ${PROJECT_NAME} Threads::Threads)
209-
target_include_directories(threadpool_test_tmp PRIVATE ${PROJECT_SOURCE_DIR}/doctest)
210-
set_target_properties(threadpool_test_tmp PROPERTIES OUTPUT_NAME "threadpool")
211-
add_test(WorkStealingQueue.Owner ${TF_UTEST_DIR}/threadpool -tc=WSQ.Owner)
212-
add_test(WorkStealingQueue.1Thief ${TF_UTEST_DIR}/threadpool -tc=WSQ.1Thief)
213-
add_test(WorkStealingQueue.2Thieves ${TF_UTEST_DIR}/threadpool -tc=WSQ.2Thieves)
214-
add_test(WorkStealingQueue.3Thieves ${TF_UTEST_DIR}/threadpool -tc=WSQ.3Thieves)
215-
add_test(WorkStealingQueue.4Thieves ${TF_UTEST_DIR}/threadpool -tc=WSQ.4Thieves)
216-
add_test(simple_threadpool ${TF_UTEST_DIR}/threadpool -tc=SimpleThreadpool)
217-
add_test(proactive_threadpool ${TF_UTEST_DIR}/threadpool -tc=ProactiveThreadpool)
218-
add_test(speculative_threadpool ${TF_UTEST_DIR}/threadpool -tc=SpeculativeThreadpool)
219-
add_test(work_stealing_threadpool ${TF_UTEST_DIR}/threadpool -tc=WorkStealingThreadpool)
203+
# unittest for executor
204+
add_executable(executor_test_tmp unittest/executor.cpp)
205+
target_link_libraries(executor_test_tmp ${PROJECT_NAME} Threads::Threads)
206+
target_include_directories(executor_test_tmp PRIVATE ${PROJECT_SOURCE_DIR}/doctest)
207+
set_target_properties(executor_test_tmp PROPERTIES OUTPUT_NAME "executor")
208+
add_test(WorkStealingQueue.Owner ${TF_UTEST_DIR}/executor -tc=WSQ.Owner)
209+
add_test(WorkStealingQueue.1Thief ${TF_UTEST_DIR}/executor -tc=WSQ.1Thief)
210+
add_test(WorkStealingQueue.2Thieves ${TF_UTEST_DIR}/executor -tc=WSQ.2Thieves)
211+
add_test(WorkStealingQueue.3Thieves ${TF_UTEST_DIR}/executor -tc=WSQ.3Thieves)
212+
add_test(WorkStealingQueue.4Thieves ${TF_UTEST_DIR}/executor -tc=WSQ.4Thieves)
213+
add_test(simple_executor ${TF_UTEST_DIR}/executor -tc=SimpleExecutor)
214+
add_test(proactive_executor ${TF_UTEST_DIR}/executor -tc=ProactiveExecutor)
215+
add_test(speculative_executor ${TF_UTEST_DIR}/executor -tc=SpeculativeExecutor)
216+
add_test(work_stealing_executor ${TF_UTEST_DIR}/executor -tc=WorkStealingExecutor)
217+
add_test(eigen_work_stealing_executor ${TF_UTEST_DIR}/executor -tc=EigenWorkStealingExecutor)
220218

221219
# threadpool_cxx14 unittest (contributed by Glen Fraser)
222220
add_executable(threadpool_cxx14_tmp unittest/threadpool_cxx14.cpp)

LICENSE

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2121
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2222
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2323
SOFTWARE.
24-

README.md

Lines changed: 47 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,13 @@ allowing users to quickly master our parallel task programming model in a natura
3333
| :------------: | :-------------: |
3434
| ![](image/static_graph.png) | <img align="right" src="image/dynamic_graph.png" width="100%"> |
3535

36-
Cpp-Taskflow provides composable task dependency graphs to enable high performance and high
37-
developer productivity.
36+
Cpp-Taskflow provides a composable task dependency graph interface
37+
to enable high performance and high developer productivity at the same time.
3838

3939
<p float="left">
40-
<img src="image/fA.png" style="width:15%; height:17%">
41-
<img src="image/fB.png" style="width:15%; height:17%">
42-
<img src="image/fC.png" style="width:50%; height:17%">
40+
<img src="image/fA.png" style="width:20%">
41+
<img src="image/fB.png" style="width:20%">
42+
<img src="image/fC.png" style="width:58%">
4343
</p>
4444

4545
Cpp-Taskflow is committed to support both academic and industry research projects,
@@ -53,43 +53,27 @@ See a quick [presentation][Presentation] and
5353
visit the [documentation][wiki] to learn more about Cpp-Taskflow.
5454

5555
# Table of Contents
56-
* [Get Started with Cpp-Taskflow](#get-started-with-cpp-taskflow)
57-
* [Create a Taskflow Graph](#create-a-taskflow-graph)
58-
* [Step 1: Create a Task](#step-1-create-a-task)
59-
* [Step 2: Define Task Dependencies](#step-2-define-task-dependencies)
60-
* [Step 3: Execute the Tasks](#step-3-execute-the-tasks)
61-
* [Dynamic Tasking](#dynamic-tasking)
62-
* [Step 1: Create a Subflow](#step-1-create-a-subflow)
63-
* [Step 2: Detach or Join a Subflow](#step-2-detach-or-join-a-subflow)
64-
* [Framework](#framework)
65-
* [Create a Framework](#create-a-framework)
66-
* [Execute a Framework](#execute-a-framework)
67-
* [Framework Composition](#framework-composition)
68-
* [Debug a Taskflow Graph](#debug-a-taskflow-graph)
69-
* [Dump the Present Taskflow Graph](#dump-the-present-taskflow-graph)
70-
* [Dump a Dispatched Graph](#dump-a-dispatched-graph)
71-
* [Dump a Framework](#dump-a-framework)
72-
* [API Reference](#api-reference)
73-
* [Taskflow API](#taskflow-api)
74-
* [<em>emplace/placeholder</em>](#emplaceplaceholder)
75-
* [<em>linearize</em>](#linearize)
76-
* [<em>parallel_for</em>](#parallel_for)
77-
* [<em>reduce/transform_reduce</em>](#reducetransform_reduce)
78-
* [<em>dispatch/silent_dispatch/wait_for_topologies/wait_for_all</em>](#dispatchsilent_dispatchwait_for_topologieswait_for_all)
79-
* [Task API](#task-api)
80-
* [<em>name</em>](#name)
81-
* [<em>work</em>](#work)
82-
* [<em>precede</em>](#precede)
83-
* [<em>gather</em>](#gather)
84-
* [Caveats](#caveats)
85-
* [System Requirements](#system-requirements)
86-
* [Compile Unit Tests and Examples](#compile-unit-tests-and-examples)
87-
* [Unit Tests](#unit-tests)
88-
* [Examples](#examples)
89-
* [Get Involved](#get-involved)
90-
* [Who is Using Cpp-Taskflow?](#who-is-using-cpp-taskflow)
91-
* [Contributors](#contributors)
92-
* [License](#license)
56+
57+
* [Get Started with Cpp-Taskflow](#get-started-with-cpp-taskflow)
58+
* [Create a Taskflow Graph](#create-a-taskflow-graph)
59+
* [Step 1: Create a Task](#step-1-create-a-task)
60+
* [Step 2: Define Task Dependencies](#step-2-define-task-dependencies)
61+
* [Step 3: Execute the Tasks](#step-3-execute-the-tasks)
62+
* [Dynamic Tasking](#dynamic-tasking)
63+
* [Step 1: Create a Subflow](#step-1-create-a-subflow)
64+
* [Step 2: Detach or Join a Subflow](#step-2-detach-or-join-a-subflow)
65+
* [Framework](#framework)
66+
* [Step 1: Create a Framework](#step-1-create-a-framework)
67+
* [Step 2: Execute a Framework](#step-2-execute-a-framework)
68+
* [Step 3: Framework Composition](#step-3-framework-composition)
69+
* [Debug a Taskflow Graph](#debug-a-taskflow-graph)
70+
* [API Reference](#api-reference)
71+
* [Caveats](#caveats)
72+
* [System Requirements](#system-requirements)
73+
* [Compile Unit Tests and Examples](#compile-unit-tests-and-examples)
74+
* [Get Involved](#get-involved)
75+
* [Who is Using Cpp-Taskflow?](#who-is-using-cpp-taskflow)
76+
* [Contributors](#contributors)
9377

9478

9579
# Get Started with Cpp-Taskflow
@@ -214,12 +198,11 @@ A.gather(B); // A runs after B
214198

215199
## Step 3: Execute the Tasks
216200

217-
There are three methods to execute a task dependency graph,
218-
`dispatch`, `silent_dispatch`, and `wait_for_all`.
201+
You can use non-blocking `dispatch` or blocking `wait_for_all`
202+
to execute a task dependency graph.
219203

220204
```cpp
221-
auto future = tf.dispatch(); // non-blocking, returns with a future immediately.
222-
tf.silent_dispatch(); // non-blocking, no return
205+
auto future = tf.dispatch(); // non-blocking, returns with a future
223206
```
224207

225208
Calling `wait_for_all` will block until all tasks complete.
@@ -417,7 +400,7 @@ In many situations, you might want to execute a task graph multiple times and th
417400
designed for this purpose. The `tf::Framework` allows you to create reusable task dependency graphs
418401
and you can compose several task graphs to build a large task graph.
419402

420-
## Create a Framework
403+
## Step 1: Create a Framework
421404
The `tf::Framework` provides the same API as `tf::Taskflow` to create tasks.
422405
The following example shows using `tf::Framework` to create a task graph .
423406

@@ -445,7 +428,7 @@ A.precede(B); // A runs before B
445428
B.precede(C, D); // B runs before C and D
446429
```
447430
448-
## Execute a Framework
431+
## Step 2: Execute a Framework
449432
Cpp-Taskflow has a rich set of methods to run a framework. You can execute a framework
450433
for a certain number of times or until a stopping criteria is met.
451434
Following example demonstrates the APIs for executing a framework.
@@ -487,7 +470,7 @@ All framework execution methods return a [std::shared_future][std::shared_future
487470
to let you query the execution status.
488471

489472

490-
## Framework Composition
473+
## Step 3: Framework Composition
491474
A powerful feature of `tf::Framework` is its composability. You can create task graphs for
492475
different parts of your workload and compose them to build a whole task graph through the `composed_of` method.
493476

@@ -522,11 +505,11 @@ f2A.precede(f1_module_task);
522505
f2B.precede(f1_module_task);
523506
f1_module_task.precede(f2C);
524507
```
525-
The `composed_of` method returns a *module task* and you can use the `precede` and `gather`
526-
methods to define its dependencies. A framework can be used to compose multiple
527-
frameworks and a framework can compose the resulting frameworks to achieve nested composition.
528-
529508
509+
The `composed_of` method returns a *module task* and you can use the `precede` and `gather`
510+
methods to define its dependencies.
511+
You can compose a framework from multiple frameworks and use the resulting framework
512+
to compose another larger ones and so on so forth.
530513
531514
532515
# Debug a Taskflow Graph
@@ -625,11 +608,10 @@ auto [f1A, f1B, f1C] = f1.emplace(
625608
[]() { std::cout << "Task f1B\n"; },
626609
[]() { std::cout << "Task f1C\n"; }
627610
);
611+
628612
f1A.precede(f1B, f1C).name("f1A");
629613
f1B.name("f1B");
630614
f1C.name("f1C");
631-
632-
// Name the framework
633615
f1.name("f1");
634616
635617
tf::Framework f2;
@@ -639,45 +621,40 @@ auto [f2A, f2B, f2C] = f2.emplace(
639621
[]() { std::cout << "Task f2B\n"; },
640622
[]() { std::cout << "Task f2C\n"; }
641623
);
642-
// Compose framework f1
624+
643625
auto f1_module_task = f2.composed_of(f1);
644626
f2A.precede(f1_module_task).name("f2A");
645627
f2B.precede(f1_module_task).name("f2B");
646628
f1_module_task.precede(f2C).name("module_f1");
647-
f2C.name("f2C");
648629
649-
// Name the framework
630+
f2C.name("f2C");
650631
f2.name("f2");
651632
652-
// Dump the framework
653-
f2.dump(std::cout);
633+
f2.dump(std::cout); // dump the framework
654634
```
655635

656-
657-
658-
659-
660636
# API Reference
661637

638+
The official [documentation][wiki] explains the complete list of
639+
Cpp-Taskflow API.
640+
In section, we highlight a short list of commonly used methods.
641+
662642
## Taskflow API
663643

664644
The class `tf::Taskflow` is the main place to create and execute task dependency graph.
665645
The table below summarizes a list of commonly used methods.
666-
Visit [documentation][wiki] to see the complete list.
646+
667647

668648
| Method | Argument | Return | Description |
669649
| -------- | --------- | ------- | ----------- |
670-
| Taskflow | none | none | construct a taskflow with the worker count equal to max hardware concurrency |
671650
| Taskflow | size | none | construct a taskflow with a given number of workers |
672651
| emplace | callables | tasks | create a task with a given callable(s) |
673652
| placeholder | none | task | insert a node without any work; work can be assigned later |
674-
| linearize | task list | none | create a linear dependency in the given task list |
675653
| parallel_for | beg, end, callable, group | task pair | apply the callable in parallel and group-by-group to the result of dereferencing every iterator in the range |
676654
| parallel_for | beg, end, step, callable, group | task pair | apply the callable in parallel and group-by-group to a index-based range |
677655
| reduce | beg, end, res, bop | task pair | reduce a range of elements to a single result through a binary operator |
678656
| transform_reduce | beg, end, res, bop, uop | task pair | apply a unary operator to each element in the range and reduce them to a single result through a binary operator |
679657
| dispatch | none | future | dispatch the current graph and return a shared future to block on completion |
680-
| silent_dispatch | none | none | dispatch the current graph |
681658
| wait_for_all | none | none | dispatch the current graph and block until all graphs finish, including all previously dispatched ones, and then clear all graphs |
682659
| wait_for_topologies | none | none | block until all dispatched graphs (topologies) finish, and then clear these graphs |
683660
| num_nodes | none | size | query the number of nodes in the current graph |
@@ -708,17 +685,6 @@ A.precede(B);
708685
B.work([](){ /* do something */ });
709686
```
710687

711-
### *linearize*
712-
713-
The method `linearize` lets you add a linear dependency between each adjacent pair of a task sequence.
714-
715-
<img align="right" width="40%" src="image/linearize.png">
716-
717-
```cpp
718-
// linearize five tasks
719-
tf.linearize(A, B, C, D);
720-
```
721-
722688
### *parallel_for*
723689

724690
The method `parallel_for` creates a subgraph that applies the callable to each item in the given range of
@@ -821,11 +787,10 @@ auto [S, T] = tf.transform_reduce(v.begin(), v.end(), min,
821787

822788
By default, all reduce methods distribute the workload evenly across threads.
823789

824-
### *dispatch/silent_dispatch/wait_for_topologies/wait_for_all*
790+
### *dispatch/wait_for_topologies/wait_for_all*
825791

826792
Dispatching a taskflow graph will schedule threads to execute the current graph and return immediately.
827-
The method `dispatch` gives you a [std::future][std::future] object to probe the execution progress while
828-
`silent_dispatch` doesn't.
793+
The method `dispatch` gives you a [std::future][std::future] object to probe the execution progress.
829794

830795
```cpp
831796
auto future = tf.dispatch();
@@ -859,7 +824,6 @@ and return a *task handle* to you.
859824
A task handle is a lightweight object that defines a set of methods for users to
860825
access and modify the attributes of the associated task.
861826
The table below summarizes the list of commonly used methods.
862-
Visit [documentation][wiki] to see the complete list.
863827

864828
| Method | Argument | Return | Description |
865829
| -------------- | ----------- | ------ | ----------- |

0 commit comments

Comments
 (0)