FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

before merge · 728443778/cpp-taskflow@1a1a346 · GitHub

Repository navigation

Commit 1a1a346

Browse files
before merge
1 parent ce32fbb commit 1a1a346

6 files changed

Lines changed: 303 additions & 330 deletions

File tree

‎README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -610,7 +610,7 @@ std::cout << "all topologies complete" << '\n';
610610

611611
## Task API
612612

613-
Each `tf::Taskflow::Task` object is a lightweight handle for you to create dependencies in its associated graph.
613+
Each task object is a lightweight handle for you to create dependencies in its associated graph.
614614
The table below summarizes its methods.
615615

616616
| Method | Argument | Return | Description |

‎doc/faq.md‎

Lines changed: 43 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,24 @@
33
This page summarizes a list of frequently asked questions about Cpp-Taskflow.
44
If you cannot find a solution here, please post an issue [here][Github issues].
55

6+
+ [General Questions](#General-Questions)
7+
+ [Compilation Issues](#Compilation-Issues)
8+
+ [Programming Questions](#Programming-Questions)
9+
10+
---
11+
612
## General Questions
713

8-
#### Q: How do I use Cpp-Taskflow in my projects?
14+
### Q: How do I use Cpp-Taskflow in my projects?
915

10-
**A:** Cpp-Taskflow is a header-only library with zero dependencies.
16+
Cpp-Taskflow is a header-only library with zero dependencies.
1117
The only thing you need is a [C++17][C++17] compiler.
1218
To use Cpp-Taskflow, simply drop the folder
1319
[taskflow](../taskflow) to your project and include [taskflow.hpp](../taskflow/taskflow.hpp).
1420

15-
#### Q: What is the difference between static tasking and dynamic tasking?
21+
### Q: What is the difference between static tasking and dynamic tasking?
1622

17-
**A:** Static tasking refers to those tasks created before execution,
23+
Static tasking refers to those tasks created before execution,
1824
while dynamic tasking refers to those tasks created during the execution of static tasks
1925
or dynamic tasks (nested).
2026
Dynamic tasks created by the same task node are grouped together to a subflow.
@@ -24,37 +30,39 @@ Dynamic tasks created by the same task node are grouped together to a subflow.
2430
| ![](../image/static_graph.png) | ![](../image/dynamic_graph.png) |
2531

2632

27-
#### Q: How many tasks can Cpp-Taskflow handle?
33+
### Q: How many tasks can Cpp-Taskflow handle?
2834

29-
**A:** Cpp-Taskflow is a very lightweight and efficient tasking library.
35+
Cpp-Taskflow is a very lightweight and efficient tasking library.
3036
It has been applied in many academic and industry projects to scale up their existing workload.
3137
A research project [OpenTimer][OpenTimer] has used Cpp-Taskflow to deal with hundreds of millions of tasks.
3238

33-
#### Q: What are the differences between Cpp-Taskflow and other tasking libraries?
39+
### Q: What are the differences between Cpp-Taskflow and other tasking libraries?
3440

35-
**A:** From our humble opinion, Cpp-Taskflow is superior in its tasking API, interface, and performance.
41+
From our humble opinion, Cpp-Taskflow is superior in its tasking API, interface, and performance.
3642
In most cases, users can quickly master Cpp-Taskflow to create large and complex dependency graphs
3743
in just a few minutes.
3844
The performance scales very well and is comparable to hard-coded multi-threading.
3945
Of course, the judge is always left for users -:)
4046

41-
#### Q: What is the weird hex value, like 0x7fc39d402ab0, in the dumped graph?
47+
### Q: What is the weird hex value, like 0x7fc39d402ab0, in the dumped graph?
4248

43-
**A:** Each task has a method `name(const std::string&)` for user to assign a human readable string
49+
Each task has a method `name(const std::string&)` for user to assign a human readable string
4450
to ease the debugging process.
4551
If a task is not assigned a name or is an internal node,
4652
its address value in the memory is used instead.
4753

48-
## Compile Issues
54+
---
4955

50-
#### Q: I can't get Cpp-Taskflow compiled in my project!
56+
## Compilation Issues
5157

52-
**A:** Please make sure your compile supports the latest version of [C++17][C++17].
58+
### Q: I can't get Cpp-Taskflow compiled in my project!
59+
60+
Please make sure your compile supports the latest version of [C++17][C++17].
5361
Make sure your project meets the System Requirements described at [README][README].
5462

55-
#### Q: Clang can't compile due to the use of std::variant.
63+
### Q: Clang can't compile due to the use of std::variant.
5664

57-
**A:** Cpp-Taskflow uses `std::variant` to enable uniform interface between static and dynamic tasking.
65+
Cpp-Taskflow uses `std::variant` to enable uniform interface between static and dynamic tasking.
5866
However it has been reported in
5967
[Clang Bug 31852](https://bugs.llvm.org/show_bug.cgi?id=31852) that
6068
clang-6.0 (and before) does not correctly pick up the friend declaration with auto-deduced return type.
@@ -71,11 +79,13 @@ For clang users, you will need to use this patch in `taskflow.hpp` as follows:
7179
#endif
7280
```
7381

82+
---
83+
7484
## Programming Questions
7585

76-
#### Q: What is the difference between Cpp-Taskflow threads and workers?
86+
### Q: What is the difference between Cpp-Taskflow threads and workers?
7787

78-
**A:** The master thread owns the thread pool and can spawn workers to run tasks
88+
The master thread owns the thread pool and can spawn workers to run tasks
7989
or shutdown the pool.
8090
Giving taskflow `N` threads means using `N` threads to do the works,
8191
and there is a total of `N+1` threads (including the master threads) in the program.
@@ -86,39 +96,40 @@ tf::Taskflow(N); // N workers, N+1 threads in the program.
8696
8797
If there is no worker threads in the pool, the master thread will do all the works by itself.
8898
89-
#### Q: Is taskflow thread-safe?
90-
**A:** No, the taskflow object is not thread-safe. You can't create tasks from multiple threads
99+
### Q: Is taskflow thread-safe?
100+
No, the taskflow object is not thread-safe. You can't create tasks from multiple threads
91101
at the same time.
92102
93-
#### Q: My program hangs and never returns after dispatching a taskflow graph. What's wrong?
103+
### Q: My program hangs and never returns after dispatching a taskflow graph. What's wrong?
94104
95-
**A:** When the program hangs forever it is very likely your taskflow graph has a cycle.
105+
When the program hangs forever it is very likely your taskflow graph has a cycle.
96106
Try the `dump` method to debug the graph before dispatching your taskflow graph.
97107
If there is no cycle, make sure you are using `future.get()` in the right way,
98108
i.e., not blocking your control flow.
99109
100-
#### Q: In the following example where B spawns a joined subflow of two tasks B1 and B2, do they run concurrently with task A?
110+
### Q: In the following example where B spawns a joined subflow of two tasks B1 and B2, do they run concurrently with task A?
101111
102112
<p>
103113
<img src="../image/dynamic_graph.png" width="60%">
104114
</p>
105115
106-
**A:** No. The subflow is spawned during the execution of B, and at this point A must finish
116+
No. The subflow is spawned during the execution of B, and at this point A must finish
107117
because A precedes B. This gives rise to the fact B1 and B2 must run after A.
108118
This graph may looks strange because B seems to run twice!
109119
However, Cpp-Taskflow will schedule B only once to create its subflow.
110120
Whether this subflow joins or detaches from B only affects the future object returned from B.
111121
112-
#### Q: How can I parallelize multiple runs on the same function with different arguments?
122+
### Q: How can I parallelize multiple runs on the same function with different arguments?
123+
124+
Many people have been asking how to apply Taskflow's `parallel_for` method
125+
to parallelize a sequential loop over an index sequence.
113126
114127
```cpp
115128
for(int i=0; i<N; ++i) {
116129
func(i); // each call to func is independent of each other
117130
}
118131
```
119132

120-
**A:** Many people have been asking how to apply Taskflow's `parallel_for` method
121-
to parallelize a sequential loop over an index sequence.
122133
This can be done by using the capture property of a C++ lambda.
123134

124135
```cpp
@@ -131,6 +142,12 @@ for(int i=0; i<N; ++i) {
131142
tf.wait_for_all();
132143
```
133144
145+
### Q: What is a Taskflow::Task?
146+
147+
A `Taskflow::Task` is a lightweight handle associated with an internal graph node
148+
for users to build task dependencies.
149+
We do not allow users to explicitly access the internal node but using this wrapper
150+
to assign different attributes to a graph node.
134151
135152
* * *
136153
[Github issues]: https://github.com/cpp-taskflow/cpp-taskflow/issues

‎example/taskflow.cpp‎

Lines changed: 59 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// 2018/09/18 - created by Tsung-Wei Huang
1+
// 2018/09/19 - created by Tsung-Wei Huang
22
//
33
// This program is used to benchmark the taskflow under different types
44
// of workloads.
@@ -29,6 +29,57 @@ using tf_privatized_t = tf::BasicTaskflow<std::function, tf::PrivatizedThreadpo
2929
std::cout << "Taskflow [privatized + std::func] elapsed time: " \
3030
<< F<tf_privatized_t>() << " ms\n"; \
3131

32+
// ============================================================================
33+
// Dynamic Stem
34+
// ============================================================================
35+
36+
// Function: dynamic_stem
37+
template <typename T>
38+
auto dynamic_stem() {
39+
40+
auto beg = std::chrono::high_resolution_clock::now();
41+
42+
const int L = 1024;
43+
44+
std::atomic<size_t> sum {0};
45+
46+
T tf;
47+
48+
std::optional<tf::Task> prev;
49+
50+
for(int l=0; l<L; ++l) {
51+
auto curr = tf.silent_emplace([&, l] (auto& subflow) {
52+
sum.fetch_add(1, std::memory_order_relaxed);
53+
std::optional<tf::Task> p;
54+
for(int k=0; k<L; k++) {
55+
auto c = subflow.silent_emplace([&] () {
56+
sum.fetch_add(1, std::memory_order_relaxed);
57+
});
58+
if(p) {
59+
p->precede(c);
60+
}
61+
p = c;
62+
}
63+
if(l & 1) {
64+
subflow.detach();
65+
}
66+
});
67+
68+
if(prev) {
69+
prev->precede(curr);
70+
}
71+
prev = curr;
72+
}
73+
74+
tf.wait_for_all();
75+
76+
assert(sum == L*(L+1));
77+
78+
auto end = std::chrono::high_resolution_clock::now();
79+
80+
return std::chrono::duration_cast<std::chrono::milliseconds>(end - beg).count();
81+
}
82+
3283
// ============================================================================
3384
// Map-Reduce
3485
// ============================================================================
@@ -46,7 +97,7 @@ auto map_reduce() {
4697

4798
T tf;
4899

49-
std::optional<typename T::TaskType> prev;
100+
std::optional<typename T::Task> prev;
50101

51102
for(int i=0; i<num_batches; ++i) {
52103

@@ -87,7 +138,7 @@ auto level_graph() {
87138

88139
T tf;
89140

90-
std::vector< std::vector<typename T::TaskType> > tasks;
141+
std::vector< std::vector<typename T::Task> > tasks;
91142

92143
tasks.resize(num_levels);
93144
for(int l=0; l<num_levels; ++l) {
@@ -132,7 +183,7 @@ auto linear_graph() {
132183

133184
T tf;
134185

135-
std::vector<typename T::TaskType> tasks;
186+
std::vector<typename T::Task> tasks;
136187

137188
for(int i=0; i<num_nodes; ++i) {
138189
tasks.push_back(tf.silent_emplace([&] () { ++sum; }));
@@ -163,9 +214,9 @@ auto binary_tree() {
163214
T tf;
164215

165216
std::atomic<size_t> sum {0};
166-
std::function<void(int, typename T::TaskType)> insert;
217+
std::function<void(int, typename T::Task)> insert;
167218

168-
insert = [&] (int l, typename T::TaskType parent) {
219+
insert = [&] (int l, typename T::Task parent) {
169220

170221
if(l < num_levels) {
171222

@@ -257,13 +308,14 @@ auto atomic_add() {
257308

258309
// Function: main
259310
int main(int argc, char* argv[]) {
260-
311+
261312
BENCHMARK("Empty Jobs", empty_jobs);
262313
BENCHMARK("Atomic Add", atomic_add);
263314
BENCHMARK("Binary Tree", binary_tree);
264315
BENCHMARK("Linear Graph", linear_graph);
265316
BENCHMARK("Level Graph", level_graph);
266317
BENCHMARK("Map Reduce", map_reduce);
318+
BENCHMARK("Dynamic Stem", dynamic_stem);
267319

268320
return 0;
269321
}

0 commit comments

Comments
 (0)

Back | FazBrowse Home | New Git URL