This source file includes following definitions.
- BOOST_AUTO_TEST_SUITE
- BOOST_AUTO_TEST_CASE_TEMPLATE
- BOOST_AUTO_TEST_CASE_TEMPLATE
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 #include "stdafx.h"
22
23 #define BOOST_TEST_MODULE libjmmcg_tests
24 #include <boost/test/included/unit_test.hpp>
25
26 #include <boost/test/test_case_template.hpp>
27 #include <boost/mpl/list.hpp>
28
29 #include "core/thread_pool_sequential.hpp"
30 #include "core/thread_pool_workers.hpp"
31
32 #include <boost/graph/graphviz.hpp>
33
34 #include <chrono>
35 #include <random>
36
37 using namespace jmmcg;
38 using namespace jmmcg::ppd;
39
40 using timed_results_t=ave_deviation_meter<unsigned long long>;
41
42 template<class Db, pool_traits::size_mode_t Sz, generic_traits::return_data Jn, class Mdl, unsigned int PoolSize=0, unsigned long GSSk=1>
43 struct erew_normal_fifo_t {
44 typedef api_lock_traits<platform_api, Mdl> lock_traits;
45 typedef safe_colln<
46 std::vector<long>,
47 typename lock_traits::nonrecursive_anon_mutex_type
48 > vtr_colln_t;
49
50 typedef pool_aspects<
51 Jn,
52 platform_api,
53 Mdl,
54 pool_traits::normal_fifo,
55 std::less,
56 GSSk
57
58
59 > thread_pool_traits;
60
61 typedef thread_pool<Db, Sz, thread_pool_traits> pool_type;
62
63 static constexpr typename pool_type::pool_type::size_type pool_size=PoolSize;
64 };
65
66 template<class Db, pool_traits::size_mode_t Sz, generic_traits::return_data Jn, class Mdl, unsigned int PoolSize=0, unsigned long GSSk=1>
67 struct erew_normal_lifo_t {
68 typedef api_lock_traits<platform_api, Mdl> lock_traits;
69 typedef safe_colln<
70 std::vector<long>,
71 typename lock_traits::nonrecursive_anon_mutex_type
72 > vtr_colln_t;
73
74 typedef pool_aspects<
75 Jn,
76 platform_api,
77 Mdl,
78 pool_traits::normal_lifo,
79 std::less,
80 GSSk
81
82
83 > thread_pool_traits;
84
85 typedef thread_pool<Db, Sz, thread_pool_traits> pool_type;
86
87 static constexpr typename pool_type::pool_type::size_type pool_size=PoolSize;
88 };
89
90 template<class Db, pool_traits::size_mode_t Sz, generic_traits::return_data Jn, class Mdl, unsigned int PoolSize=0, unsigned long GSSk=1>
91 struct erew_priority_queue_t {
92 typedef api_lock_traits<platform_api, Mdl> lock_traits;
93 typedef safe_colln<
94 std::vector<long>,
95 typename lock_traits::nonrecursive_anon_mutex_type
96 > vtr_colln_t;
97
98 typedef pool_aspects<
99 Jn,
100 platform_api,
101 Mdl,
102 pool_traits::prioritised_queue,
103 std::less,
104 GSSk
105
106
107 > thread_pool_traits;
108
109 typedef thread_pool<Db, Sz, thread_pool_traits> pool_type;
110
111 static constexpr typename pool_type::pool_type::size_type pool_size=PoolSize;
112 };
113
114 template<class Db, pool_traits::size_mode_t Sz, generic_traits::return_data Jn, class Mdl, unsigned int PoolSize=0, unsigned long GSSk=1UL>
115 struct crew_normal_fifo_t {
116 typedef api_lock_traits<platform_api, Mdl> lock_traits;
117 typedef safe_colln<
118 std::vector<long>,
119 typename lock::rw::locker<lock_traits>,
120 typename lock::rw::locker<lock_traits>::decaying_write_lock_type
121 > vtr_colln_t;
122
123 typedef pool_aspects<
124 Jn,
125 platform_api,
126 Mdl,
127 pool_traits::normal_fifo,
128 std::less,
129 GSSk
130
131
132 > thread_pool_traits;
133
134 typedef thread_pool<Db, Sz, thread_pool_traits> pool_type;
135
136 static constexpr typename pool_type::pool_type::size_type pool_size=PoolSize;
137 };
138
139 template<class Db, pool_traits::size_mode_t Sz, generic_traits::return_data Jn, class Mdl, unsigned int PoolSize=0, unsigned long GSSk=1UL>
140 struct crew_normal_lifo_t {
141 typedef api_lock_traits<platform_api, Mdl> lock_traits;
142 typedef safe_colln<
143 std::vector<long>,
144 typename lock::rw::locker<lock_traits>,
145 typename lock::rw::locker<lock_traits>::decaying_write_lock_type
146 > vtr_colln_t;
147
148 typedef pool_aspects<
149 Jn,
150 platform_api,
151 Mdl,
152 pool_traits::normal_lifo,
153 std::less,
154 GSSk
155
156
157 > thread_pool_traits;
158
159 typedef thread_pool<Db, Sz, thread_pool_traits> pool_type;
160
161 static constexpr typename pool_type::pool_type::size_type pool_size=PoolSize;
162 };
163
164 template<class Db, pool_traits::size_mode_t Sz, generic_traits::return_data Jn, class Mdl, unsigned int PoolSize=0, unsigned long GSSk=1UL>
165 struct crew_normal_lifo_lockfree_t {
166 typedef api_lock_traits<platform_api, Mdl> lock_traits;
167 typedef safe_colln<
168 std::vector<long>,
169 typename lock::rw::locker<lock_traits>,
170 typename lock::rw::locker<lock_traits>::decaying_write_lock_type
171 > vtr_colln_t;
172
173 typedef pool_aspects<
174 Jn,
175 platform_api,
176 Mdl,
177 pool_traits::normal_lifo_lockfree,
178 std::less,
179 GSSk
180
181
182 > thread_pool_traits;
183
184 typedef thread_pool<Db, Sz, thread_pool_traits> pool_type;
185
186 static constexpr typename pool_type::pool_type::size_type pool_size=PoolSize;
187 };
188
189 template<class Db, pool_traits::size_mode_t Sz, generic_traits::return_data Jn, class Mdl, unsigned int PoolSize=0, unsigned long GSSk=1>
190 struct crew_priority_queue_t {
191 typedef api_lock_traits<platform_api, Mdl> lock_traits;
192 typedef safe_colln<
193 std::vector<long>,
194 typename lock::rw::locker<lock_traits>,
195 typename lock::rw::locker<lock_traits>::decaying_write_lock_type
196 > vtr_colln_t;
197
198 typedef pool_aspects<
199 Jn,
200 platform_api,
201 Mdl,
202 pool_traits::prioritised_queue,
203 std::less,
204 GSSk
205
206
207 > thread_pool_traits;
208
209 typedef thread_pool<Db, Sz, thread_pool_traits> pool_type;
210
211 static constexpr typename pool_type::pool_type::size_type pool_size=PoolSize;
212 };
213
214 typedef boost::mpl::list<
215 erew_normal_fifo_t<pool_traits::work_distribution_mode_t::worker_threads_get_work<pool_traits::work_distribution_mode_t::queue_model_t::pool_owns_queue>, pool_traits::size_mode_t::fixed_size, generic_traits::return_data::joinable, heavyweight_threading, 1>,
216 erew_normal_lifo_t<pool_traits::work_distribution_mode_t::worker_threads_get_work<pool_traits::work_distribution_mode_t::queue_model_t::pool_owns_queue>, pool_traits::size_mode_t::fixed_size, generic_traits::return_data::joinable, heavyweight_threading, 1>,
217 crew_normal_fifo_t<pool_traits::work_distribution_mode_t::worker_threads_get_work<pool_traits::work_distribution_mode_t::queue_model_t::pool_owns_queue>, pool_traits::size_mode_t::fixed_size, generic_traits::return_data::joinable, heavyweight_threading, 1>,
218 crew_normal_lifo_t<pool_traits::work_distribution_mode_t::worker_threads_get_work<pool_traits::work_distribution_mode_t::queue_model_t::pool_owns_queue>, pool_traits::size_mode_t::fixed_size, generic_traits::return_data::joinable, heavyweight_threading, 1>,
219 crew_normal_lifo_lockfree_t<pool_traits::work_distribution_mode_t::worker_threads_get_work<pool_traits::work_distribution_mode_t::queue_model_t::pool_owns_queue>, pool_traits::size_mode_t::fixed_size, generic_traits::return_data::joinable, heavyweight_threading, 1>,
220 crew_normal_lifo_lockfree_t<pool_traits::work_distribution_mode_t::worker_threads_get_work<pool_traits::work_distribution_mode_t::queue_model_t::thread_owns_queue<pool_traits::work_distribution_mode_t::queue_model_t::stealing_mode_t::random>>, pool_traits::size_mode_t::fixed_size, generic_traits::return_data::joinable, heavyweight_threading, 1>
221 > dataflow_ps1_test_types;
222
223 typedef boost::mpl::list<
224 erew_normal_fifo_t<pool_traits::work_distribution_mode_t::worker_threads_get_work<pool_traits::work_distribution_mode_t::queue_model_t::pool_owns_queue>, pool_traits::size_mode_t::fixed_size, generic_traits::return_data::joinable, heavyweight_threading, 12>,
225 erew_normal_lifo_t<pool_traits::work_distribution_mode_t::worker_threads_get_work<pool_traits::work_distribution_mode_t::queue_model_t::pool_owns_queue>, pool_traits::size_mode_t::fixed_size, generic_traits::return_data::joinable, heavyweight_threading, 12>,
226 crew_normal_fifo_t<pool_traits::work_distribution_mode_t::worker_threads_get_work<pool_traits::work_distribution_mode_t::queue_model_t::pool_owns_queue>, pool_traits::size_mode_t::fixed_size, generic_traits::return_data::joinable, heavyweight_threading, 12>,
227 crew_normal_lifo_t<pool_traits::work_distribution_mode_t::worker_threads_get_work<pool_traits::work_distribution_mode_t::queue_model_t::pool_owns_queue>, pool_traits::size_mode_t::fixed_size, generic_traits::return_data::joinable, heavyweight_threading, 12>
228
229 > dataflow_ps12_test_types;
230
231 struct trivial_work {
232 constexpr trivial_work() noexcept(true) {
233 }
234 void process() noexcept(true) {
235 }
236
237 constexpr bool __fastcall operator<(trivial_work const &) const noexcept(true) {
238 return true;
239 }
240 };
241
242 template<class PT>
243 struct recusive_work {
244 typedef PT pool_type;
245 typedef typename pool_type::joinable joinable;
246
247 const unsigned long depth;
248 pool_type &pool;
249
250 constexpr recusive_work(const unsigned long d, pool_type &p) noexcept(true)
251 : depth(d), pool(p) {
252 }
253 void process() noexcept(true) {
254 if (depth>0) {
255 auto const &context1=pool<<joinable()<<recusive_work(depth-1, pool);
256 auto const &context2=pool<<joinable()<<recusive_work(depth-1, pool);
257 *context1;
258 *context2;
259 }
260 }
261
262 constexpr bool __fastcall operator<(recusive_work const &) const noexcept(true) {
263 return true;
264 }
265 };
266
267 template<class PT>
268 struct pool_1ctx_work {
269 typedef PT pool_type;
270 using joinable=typename pool_type::joinable;
271
272 unsigned long num_xfers;
273 pool_type &pool;
274
275 constexpr pool_1ctx_work(const unsigned long x, pool_type &p) noexcept(true)
276 : num_xfers(x), pool(p) {
277 }
278 void process() noexcept(true) {
279 while (--num_xfers) {
280 auto const &context=pool<<joinable()<<trivial_work();
281 *context;
282 }
283 }
284
285 constexpr bool __fastcall operator<(pool_1ctx_work const &) const noexcept(true) {
286 return true;
287 }
288 };
289
290
291
292 BOOST_AUTO_TEST_SUITE(thread_pool_tests)
293
294 BOOST_AUTO_TEST_SUITE(joinable_dataflow)
295
296 BOOST_AUTO_TEST_SUITE(finite)
297
298 BOOST_AUTO_TEST_SUITE(n_elements)
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321 BOOST_AUTO_TEST_CASE_TEMPLATE(single_vertical_dataflow_operations_rate, T, dataflow_ps1_test_types) {
322 typedef typename T::pool_type pool_type;
323
324 #ifdef JMMCG_PERFORMANCE_TESTS
325 const unsigned long test_size=2<<9;
326 const unsigned long num_reps=20000;
327 #else
328 const unsigned long test_size=2<<3;
329 const unsigned long num_reps=2;
330 #endif
331 pool_type pool(T::pool_size);
332 BOOST_CHECK_EQUAL(pool.pool_size(), 1UL);
333 std::cout<<"Pool="<<pool.pool_size()<<std::flush;
334 const std::pair<timed_results_t, bool> timed_results(compute_average_deviation<timed_results_t::value_type>(
335 1.0,
336 num_reps,
337 [test_size, &pool]() {
338 typedef typename pool_type::joinable joinable;
339
340 const auto t1=std::chrono::high_resolution_clock::now();
341 for (unsigned long num_loops=0;num_loops<test_size;++num_loops) {
342 auto const &context=pool<<joinable()<<trivial_work();
343 *context;
344 }
345 const auto t2=std::chrono::high_resolution_clock::now();
346 return timed_results_t::value_type(std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1).count());
347 }
348 ));
349 std::cout<<", time taken: "<<timed_results.first<<" usec."<<std::endl;
350 const double rescale=1.0d/(test_size*pool.pool_size());
351 std::cout<<"Vertical dataflow transfer took (usec): "<<rescale*timed_results.first.arithmetic_mean()<<std::endl;
352 std::cout<<pool.statistics()<<std::endl;
353 #ifdef JMMCG_PERFORMANCE_TESTS
354 BOOST_CHECK(!timed_results.second);
355 #endif
356 }
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425 BOOST_AUTO_TEST_CASE_TEMPLATE(vertical_dataflow_operations_rate, T, dataflow_ps12_test_types) {
426 typedef typename T::pool_type pool_type;
427
428 #ifdef JMMCG_PERFORMANCE_TESTS
429 const unsigned long test_size=2<<10;
430 const unsigned long num_reps=1000;
431 #else
432 const unsigned long test_size=2<<3;
433 const unsigned long num_reps=2;
434 #endif
435
436 pool_type pool(T::pool_size);
437 BOOST_CHECK_EQUAL(pool.pool_size(), 12UL);
438 std::cout<<"Pool="<<pool.pool_size()<<std::flush;
439 const std::pair<timed_results_t, bool> timed_results(compute_average_deviation<timed_results_t::value_type>(
440 10.0,
441 num_reps,
442 [&pool]() {
443 typedef typename pool_type::joinable joinable;
444
445 const auto t1=std::chrono::high_resolution_clock::now();
446 for (unsigned long num_loops=0;num_loops<test_size;++num_loops) {
447 auto const &context1=pool<<joinable()<<trivial_work();
448 auto const &context2=pool<<joinable()<<trivial_work();
449 auto const &context3=pool<<joinable()<<trivial_work();
450 auto const &context4=pool<<joinable()<<trivial_work();
451 auto const &context5=pool<<joinable()<<trivial_work();
452 auto const &context6=pool<<joinable()<<trivial_work();
453 auto const &context7=pool<<joinable()<<trivial_work();
454 auto const &context8=pool<<joinable()<<trivial_work();
455 auto const &context9=pool<<joinable()<<trivial_work();
456 auto const &context10=pool<<joinable()<<trivial_work();
457 auto const &context11=pool<<joinable()<<trivial_work();
458 auto const &context12=pool<<joinable()<<trivial_work();
459 *context1;
460 *context2;
461 *context3;
462 *context4;
463 *context5;
464 *context6;
465 *context7;
466 *context8;
467 *context9;
468 *context10;
469 *context11;
470 *context12;
471 }
472 const auto t2=std::chrono::high_resolution_clock::now();
473 return timed_results_t::value_type(std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1).count());
474 }
475 ));
476 std::cout<<", time taken: "<<timed_results.first<<" usec."<<std::endl;
477 const double rescale=1.0d/(test_size*pool.pool_size());
478 std::cout<<"Vertical dataflow transfer took (usec): "<<rescale*timed_results.first.arithmetic_mean()<<std::endl;
479 std::cout<<pool.statistics()<<std::endl;
480 #ifdef JMMCG_PERFORMANCE_TESTS
481 BOOST_CHECK(!timed_results.second);
482 #endif
483 }
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502 BOOST_AUTO_TEST_CASE_TEMPLATE(horizontal_dataflow_transfers_rate, T, dataflow_ps12_test_types) {
503 typedef typename T::pool_type pool_type;
504
505
506 #ifdef JMMCG_PERFORMANCE_TESTS
507 const unsigned long test_size=2<<13;
508 const unsigned long num_reps=20000;
509 const unsigned long test_depth=3;
510 #else
511 const unsigned long test_size=2<<3;
512 const unsigned long num_reps=2;
513 const unsigned long test_depth=1;
514 #endif
515 pool_type pool(T::pool_size);
516 std::cout<<"Pool="<<pool.pool_size()<<std::flush;
517 const std::pair<timed_results_t, bool> timed_results(compute_average_deviation<timed_results_t::value_type>(
518 5.0,
519 num_reps,
520 [test_depth, test_size, &pool]() {
521 typedef typename pool_type::joinable joinable;
522 typedef recusive_work<pool_type> work_type;
523
524 const unsigned long test_size=1<<6;
525 const auto t1=std::chrono::high_resolution_clock::now();
526 for (unsigned long num_loops=0;num_loops<test_size;++num_loops) {
527 auto const &context=pool<<joinable()<<work_type(test_depth, pool);
528 *context;
529 }
530 const auto t2=std::chrono::high_resolution_clock::now();
531 return timed_results_t::value_type(std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1).count());
532 }
533 ));
534 std::cout<<", time taken: "<<timed_results.first<<" usec."<<std::endl;
535 const double rescale=1.0d/(test_size*pool.pool_size());
536 std::cout<<"Tree-constructions transfer took (usec): "<<rescale*timed_results.first.arithmetic_mean()<<std::endl;
537 std::cout<<pool.statistics()<<std::endl;
538 #ifdef JMMCG_PERFORMANCE_TESTS
539 BOOST_CHECK(!timed_results.second);
540 #endif
541 }
542
543 BOOST_AUTO_TEST_SUITE_END()
544
545 BOOST_AUTO_TEST_SUITE_END()
546
547 BOOST_AUTO_TEST_SUITE_END()
548
549 BOOST_AUTO_TEST_SUITE_END()