|
8 | 8 | #include <chrono> |
9 | 9 | #include <random> |
10 | 10 |
|
11 | | -// Procedure: benchmark_empty_jobs |
12 | | -void benchmark_empty_jobs() { |
| 11 | +const int thread_num = 4; |
| 12 | +const int task_num = 16; |
13 | 13 |
|
14 | | - std::cout << "Benchmarking threadpool throughput on empty jobs ...\n"; |
| 14 | +// ---------------------------------------------------------------------------- |
15 | 15 |
|
16 | | - unsigned thread_num = 4; |
17 | | - unsigned int task_num = 10000000; |
| 16 | +// Procedure: linear_insertions |
| 17 | +template <typename T> |
| 18 | +auto linear_insertions() { |
| 19 | + |
| 20 | + auto beg = std::chrono::high_resolution_clock::now(); |
18 | 21 |
|
19 | | - auto start = std::chrono::high_resolution_clock::now(); |
| 22 | + T threadpool(thread_num); |
20 | 23 |
|
21 | | - tf::ProactiveThreadpool proactive(thread_num); |
22 | | - for(size_t i=0; i<task_num; i++){ |
23 | | - proactive.silent_async([](){}); |
| 24 | + std::atomic<size_t> sum {0}; |
| 25 | + |
| 26 | + std::function<void(int)> insert; |
| 27 | + std::promise<void> promise; |
| 28 | + auto future = promise.get_future(); |
| 29 | + |
| 30 | + insert = [&threadpool, &insert, &sum, &promise] (int i) { |
| 31 | + if(i > 0) { |
| 32 | + threadpool.silent_async([i=i-1, &insert] () { |
| 33 | + insert(i); |
| 34 | + }); |
| 35 | + } |
| 36 | + else { |
| 37 | + if(++sum; sum == thread_num) { |
| 38 | + promise.set_value(); |
| 39 | + } |
| 40 | + } |
| 41 | + }; |
| 42 | + |
| 43 | + for(size_t i=0; i<thread_num; i++){ |
| 44 | + insert(task_num / thread_num); |
24 | 45 | } |
25 | | - proactive.shutdown(); |
| 46 | + |
| 47 | + // synchronize until all tasks finish |
| 48 | + threadpool.shutdown(); |
| 49 | + |
| 50 | + //future.get(); |
| 51 | + //assert(sum == thread_num); |
26 | 52 |
|
27 | 53 | auto end = std::chrono::high_resolution_clock::now(); |
28 | | - auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start); |
29 | | - std::cout << "ProactiveThreadpool elapsed time: " << elapsed.count() << " ms\n"; |
30 | 54 |
|
31 | | - start = std::chrono::high_resolution_clock::now(); |
| 55 | + return std::chrono::duration_cast<std::chrono::milliseconds>(end - beg).count(); |
| 56 | +} |
| 57 | + |
| 58 | +// Procedure: benchmark_linear_insertions |
| 59 | +void benchmark_linear_insertions() { |
| 60 | + |
| 61 | + std::cout << "==== Linear Insertions ====\n"; |
| 62 | + |
| 63 | + //std::cout << "Proactive threadpool takes: " |
| 64 | + // << linear_insertions<tf::ProactiveThreadpool>() << " ms\n"; |
| 65 | + |
| 66 | + std::cout << "Simple threadpool takes: " |
| 67 | + << linear_insertions<tf::SimpleThreadpool>() << " ms\n"; |
| 68 | +} |
| 69 | + |
| 70 | +// ---------------------------------------------------------------------------- |
| 71 | + |
| 72 | +// Function: empty_jobs |
| 73 | +template <typename T> |
| 74 | +auto empty_jobs() { |
| 75 | + |
| 76 | + auto beg = std::chrono::high_resolution_clock::now(); |
| 77 | + |
| 78 | + T threadpool(thread_num); |
32 | 79 |
|
33 | | - tf::SimpleThreadpool simple(thread_num); |
34 | 80 | for(size_t i=0; i<task_num; i++){ |
35 | | - simple.silent_async([](){}); |
| 81 | + threadpool.silent_async([](){}); |
36 | 82 | } |
37 | | - simple.shutdown(); |
| 83 | + |
| 84 | + threadpool.shutdown(); |
38 | 85 |
|
39 | | - end = std::chrono::high_resolution_clock::now(); |
40 | | - elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start); |
41 | | - std::cout << "SimpleThreadpool elapsed time: " << elapsed.count() << " ms\n"; |
| 86 | + auto end = std::chrono::high_resolution_clock::now(); |
| 87 | + |
| 88 | + return std::chrono::duration_cast<std::chrono::milliseconds>(end - beg).count(); |
42 | 89 | } |
43 | 90 |
|
44 | | -// Procedure: benchmark_atomic_add |
45 | | -void benchmark_atomic_add() { |
| 91 | +// Procedure: benchmark_empty_jobs |
| 92 | +void benchmark_empty_jobs() { |
| 93 | + std::cout << "==== Empty Jobs ====\n"; |
46 | 94 |
|
47 | | - std::cout << "Benchmarking threadpool throughput on atomic add ...\n"; |
48 | | - |
49 | | - unsigned thread_num = 4; |
50 | | - unsigned int task_num = 10000000; |
| 95 | + std::cout << "Proactive threadpool takes: " |
| 96 | + << empty_jobs<tf::ProactiveThreadpool>() << " ms\n"; |
| 97 | + |
| 98 | + std::cout << "Simple threadpool takes: " |
| 99 | + << empty_jobs<tf::SimpleThreadpool>() << " ms\n"; |
| 100 | +} |
| 101 | + |
| 102 | +// ---------------------------------------------------------------------------- |
| 103 | + |
| 104 | +// Function: atomic_add |
| 105 | +template <typename T> |
| 106 | +auto atomic_add() { |
51 | 107 |
|
52 | 108 | std::atomic<int> counter(0); |
53 | | - auto start = std::chrono::high_resolution_clock::now(); |
| 109 | + auto beg = std::chrono::high_resolution_clock::now(); |
54 | 110 |
|
55 | | - tf::ProactiveThreadpool proactive(thread_num); |
| 111 | + T threadpool(thread_num); |
56 | 112 | for(size_t i=0; i<task_num; i++){ |
57 | | - proactive.silent_async([&counter](){ counter++; }); |
| 113 | + threadpool.silent_async([&counter](){ counter++; }); |
58 | 114 | } |
59 | | - proactive.shutdown(); |
| 115 | + threadpool.shutdown(); |
| 116 | + |
| 117 | + assert(counter == task_num); |
60 | 118 |
|
61 | 119 | auto end = std::chrono::high_resolution_clock::now(); |
62 | | - auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start); |
63 | | - std::cout << "ProactiveThreadpool elapsed time: " << elapsed.count() << " ms\n"; |
| 120 | + return std::chrono::duration_cast<std::chrono::milliseconds>(end - beg).count(); |
| 121 | +} |
64 | 122 |
|
65 | | - counter = 0; |
66 | | - start = std::chrono::high_resolution_clock::now(); |
67 | | - tf::SimpleThreadpool simple(thread_num); |
| 123 | +// Procedure: benchmark_atomic_add |
| 124 | +void benchmark_atomic_add() { |
| 125 | + std::cout << "==== Atomic Add ====\n"; |
68 | 126 |
|
69 | | - for(size_t i=0; i<task_num; i++){ |
70 | | - simple.silent_async([&counter](){ counter++; }); |
71 | | - } |
72 | | - simple.shutdown(); |
73 | | - |
74 | | - end = std::chrono::high_resolution_clock::now(); |
75 | | - elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start); |
76 | | - std::cout << "SimpleThreadpool elapsed time: " << elapsed.count() << " ms\n"; |
| 127 | + std::cout << "Proactive threadpool takes: " |
| 128 | + << atomic_add<tf::ProactiveThreadpool>() << " ms\n"; |
| 129 | + |
| 130 | + std::cout << "Simple threadpool takes: " |
| 131 | + << atomic_add<tf::SimpleThreadpool>() << " ms\n"; |
77 | 132 | } |
78 | 133 |
|
79 | 134 | // Function: main |
80 | 135 | int main(int argc, char* argv[]) { |
81 | 136 |
|
82 | | - benchmark_empty_jobs(); |
83 | | - benchmark_atomic_add(); |
| 137 | + benchmark_linear_insertions(); |
| 138 | + //benchmark_empty_jobs(); |
| 139 | + //benchmark_atomic_add(); |
84 | 140 |
|
85 | 141 | return 0; |
86 | 142 | } |
0 commit comments