forked from taskflow/taskflow
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy paththreadpool_cxx14.cpp
More file actions
101 lines (93 loc) · 3.39 KB
/
threadpool_cxx14.cpp
File metadata and controls
101 lines (93 loc) · 3.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
// 2018/08/28 - contributed by Glen Fraser
//
// Simple example showing use of the C++14-compatible threadpool
// implementation. The threadpool (alone) may be used when you have
// no inter-task dependencies to express, and when you require
// C++14 for a project.
//
// NOTE: if you are using a fully C++17-compliant compiler, you should
// be including <taskflow/taskflow.hpp> rather than this file!
//
// Compile with VS2017 using:
// cl /std:c++14 /W4 /EHsc /O2 /Ipath-to-taskflow threadpool_cxx14.cpp
// Compile with clang (including Apple LLVM version 9.0.0) using:
// clang++ -std=c++14 -Wall -O3 -Ipath-to-taskflow threadpool_cxx14.cpp -o threadpool_cxx14
// (for gcc, replace clang++ with g++)
#include <taskflow/threadpool/threadpool_cxx14.hpp>
#include <iostream>
#include <random>
// The "noinline" directive is used to prevent the compiler from
// optimizing out the entire calculation, ensuring it actually does
// its (fake) work when we want it to (for testing), at runtime.
#ifdef _WIN32
__declspec(noinline)
#else
__attribute__((noinline))
#endif // _WIN32
int64_t compute(int64_t x, int64_t i, int64_t r)
{
return x + i + r;
}
int main()
{
auto numThreads = std::max(1u, std::thread::hardware_concurrency());
tf::Threadpool tp(numThreads);
std::default_random_engine gen(17);
std::uniform_int_distribution<int64_t> d{ 0, 10000 };
std::vector<std::future<int64_t>> intFutures;
std::vector<std::future<void>> voidFutures;
auto start = std::chrono::steady_clock::now();
for (auto i = 0; i < 2000; ++i) {
auto r = d(gen);
auto future = tp.async(
[i, r]() {
int64_t sum = 0;
for (int64_t x = 0; x < 10000000; ++x) {
sum += compute(x, i, r);
}
return sum;
});
intFutures.push_back(std::move(future));
voidFutures.push_back(tp.async([]() {
// Simulate a very small task that returns no value.
std::this_thread::sleep_for(std::chrono::microseconds(5));
}));
}
std::cout << "Scheduled " << intFutures.size() + voidFutures.size() << " tasks...\n";
// Wait for them all to finish (get the results)
int64_t sum = 0;
for (auto& f : intFutures) {
sum += f.get();
}
for (auto& f : voidFutures) {
f.get();
}
auto end = std::chrono::steady_clock::now();
std::cout << "...ran in "
<< std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count()
<< " milliseconds\n";
std::cout << "Remaining scheduled tasks: " << tp.num_tasks()
<< "\tWorker threads: " << tp.num_workers() << '\n';
std::cout << intFutures.size() << " int futures summed to: " << sum << '\n';
std::cout << "(also ran " << voidFutures.size() << " void futures)\n";
std::cout << "\n";
// You may also use Threadpool::wait_for_all() to synchronize -- it
// will return when all scheduled tasks have completed (even tasks
// scheduled "silently" without a future).
auto const numSilentTasks = 10;
std::mutex printMutex;
for (auto i = 0; i < numSilentTasks; ++i) {
tp.silent_async([=, &printMutex]() {
// Simulate a small task
std::this_thread::sleep_for(std::chrono::microseconds(5) * (numSilentTasks - i));
std::lock_guard<std::mutex> lock(printMutex);
std::cout << "Silent task " << i << " returning\n";
});
}
tp.wait_for_all();
{
std::lock_guard<std::mutex> lock(printMutex);
std::cout << "Main thread: all scheduled tasks are done\n";
}
return 0;
}