1/*
2 Copyright (c) 2005-2019 Intel Corporation
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17#define HARNESS_DEFAULT_MIN_THREADS 4
18#define HARNESS_DEFAULT_MAX_THREADS 8
19
20#include "harness_defs.h"
21#include <cstdio>
22#include <cstdlib>
23#include <cassert>
24#include <utility>
25#include "tbb/task.h"
26#include "tbb/task_scheduler_init.h"
27#include "tbb/tick_count.h"
28#include "tbb/parallel_for.h"
29#include "tbb/blocked_range.h"
30#include "tbb/mutex.h"
31#include "tbb/spin_mutex.h"
32#include "tbb/queuing_mutex.h"
33#include "harness.h"
34
35using namespace std;
36using namespace tbb;
37
38///////////////////// Parallel methods ////////////////////////
39
40// *** Serial shared by mutexes *** //
41int SharedI = 1, SharedN;
42template<typename M>
43class SharedSerialFibBody: NoAssign {
44 M &mutex;
45public:
46 SharedSerialFibBody( M &m ) : mutex( m ) {}
47 //! main loop
48 void operator()( const blocked_range<int>& /*range*/ ) const {
49 for(;;) {
50 typename M::scoped_lock lock( mutex );
51 if(SharedI >= SharedN) break;
52 volatile double sum = 7.3;
53 sum *= 11.17;
54 ++SharedI;
55 }
56 }
57};
58
59//! Root function
60template<class M>
61void SharedSerialFib(int n)
62{
63 SharedI = 1;
64 SharedN = n;
65 M mutex;
66 parallel_for( blocked_range<int>(0,4,1), SharedSerialFibBody<M>( mutex ) );
67}
68
69/////////////////////////// Main ////////////////////////////////////////////////////
70
71double Tsum = 0; int Tnum = 0;
72
73typedef void (*MeasureFunc)(int);
74//! Measure ticks count in loop [2..n]
75void Measure(const char *name, MeasureFunc func, int n)
76{
77 tick_count t0;
78 tick_count::interval_t T;
79 REMARK("%s",name);
80 t0 = tick_count::now();
81 for(int number = 2; number <= n; number++)
82 func(number);
83 T = tick_count::now() - t0;
84 double avg = Tnum? Tsum/Tnum : 1;
85 if (avg == 0.0) avg = 1;
86 if(avg * 100 < T.seconds()) {
87 REPORT("Warning: halting detected (%g sec, av: %g)\n", T.seconds(), avg);
88 ASSERT(avg * 1000 > T.seconds(), "Too long halting period");
89 } else {
90 Tsum += T.seconds(); Tnum++;
91 }
92 REMARK("\t- in %f msec\n", T.seconds()*1000);
93}
94
95int TestMain () {
96 MinThread = max(2, MinThread);
97 int NumbersCount = 100;
98 short recycle = 100;
99 do {
100 for(int threads = MinThread; threads <= MaxThread; threads++) {
101 task_scheduler_init scheduler_init(threads);
102 REMARK("Threads number is %d\t", threads);
103 Measure("Shared serial (wrapper mutex)\t", SharedSerialFib<mutex>, NumbersCount);
104 //sum = Measure("Shared serial (spin_mutex)", SharedSerialFib<tbb::spin_mutex>, NumbersCount);
105 //sum = Measure("Shared serial (queuing_mutex)", SharedSerialFib<tbb::queuing_mutex>, NumbersCount);
106 }
107 } while(--recycle);
108 return Harness::Done;
109}
110