1 /*
2     Copyright (c) 2005-2020 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 ////// Test configuration ////////////////////////////////////////////////////
18 #define SECONDS_RATIO 1000000 // microseconds
19 
20 #ifndef REPEAT_K
21 #define REPEAT_K 50 // repeat coefficient
22 #endif
23 
24 int outer_work[] = {/*256,*/ 64, 16, 4, 0};
25 int inner_work[] = {32, 8, 0 };
26 
27 // keep it to calibrate the time of work without synchronization
28 #define BOX1 "baseline"
29 #define BOX1TEST TimeTest< TBB_Mutex<tbb::null_mutex>, SECONDS_RATIO >
30 
31 // enable/disable tests for:
32 #define BOX2 "spin_mutex"
33 #define BOX2TEST TimeTest< TBB_Mutex<tbb::spin_mutex>, SECONDS_RATIO >
34 
35 // enable/disable tests for:
36 #define BOX3 "spin_rw_mutex"
37 #define BOX3TEST TimeTest< TBB_Mutex<tbb::spin_rw_mutex>, SECONDS_RATIO >
38 
39 // enable/disable tests for:
40 #define BOX4 "queuing_mutex"
41 #define BOX4TEST TimeTest< TBB_Mutex<tbb::queuing_mutex>, SECONDS_RATIO >
42 
43 // enable/disable tests for:
44 //#define BOX5 "queuing_rw_mutex"
45 #define BOX5TEST TimeTest< TBB_Mutex<tbb::queuing_rw_mutex>, SECONDS_RATIO >
46 
47 //////////////////////////////////////////////////////////////////////////////
48 
49 #include <cstdlib>
50 #include <math.h>
51 #include <algorithm>    // Need std::swap
52 #include <utility>      // Need std::pair
53 #include <sstream>
54 #include "tbb/tbb_stddef.h"
55 #include "tbb/null_mutex.h"
56 #include "tbb/spin_rw_mutex.h"
57 #include "tbb/spin_mutex.h"
58 #include "tbb/queuing_mutex.h"
59 #include "tbb/queuing_rw_mutex.h"
60 #include "tbb/mutex.h"
61 
62 #if INTEL_TRIAL==2
63 #include "tbb/parallel_for.h" // enable threading by TBB scheduler
64 #include "tbb/task_scheduler_init.h"
65 #include "tbb/blocked_range.h"
66 #endif
67 // for test
68 #include "time_framework.h"
69 
70 using namespace tbb;
71 using namespace tbb::internal;
72 
73 /////////////////////////////////////////////////////////////////////////////////////////
74 
75 //! base class for tests family
76 struct TestLocks : TesterBase {
77     // Inherits "value", "threads_count", and other variables
TestLocksTestLocks78     TestLocks() : TesterBase(/*number of modes*/sizeof(outer_work)/sizeof(int)) {}
79     //! returns name of test part/mode
get_nameTestLocks80     /*override*/std::string get_name(int testn) {
81         std::ostringstream buf;
82         buf.width(4); buf.fill('0');
83         buf << outer_work[testn]; // mode number
84         return buf.str();
85     }
86     //! enables results types and returns theirs suffixes
get_result_typeTestLocks87     /*override*/const char *get_result_type(int, result_t type) const {
88         switch(type) {
89             case MIN: return " min";
90             case MAX: return " max";
91             default: return 0;
92         }
93     }
94     //! repeats count
repeat_untilTestLocks95     int repeat_until(int /*test_n*/) const {
96         return REPEAT_K*100;//TODO: suggest better?
97     }
98     //! fake work
do_workTestLocks99     void do_work(int work) volatile {
100         for(int i = 0; i < work; i++) {
101             volatile int x = i;
102             __TBB_Pause(0); // just to call inline assembler
103             x *= work/threads_count;
104         }
105     }
106 };
107 
108 //! template test unit for any of TBB mutexes
109 template<typename M>
110 struct TBB_Mutex : TestLocks {
111     M mutex;
112 
testTBB_Mutex113     double test(int testn, int /*threadn*/)
114     {
115         for(int r = 0; r < repeat_until(testn); ++r) {
116             do_work(outer_work[testn]);
117             {
118                 typename M::scoped_lock with(mutex);
119                 do_work(/*inner work*/value);
120             }
121         }
122         return 0;
123     }
124 };
125 
126 /////////////////////////////////////////////////////////////////////////////////////////
127 
128 //Using BOX declarations
129 #include "time_sandbox.h"
130 
131 // run tests for each of inner work value
RunLoops(test_sandbox & the_test,int thread)132 void RunLoops(test_sandbox &the_test, int thread) {
133     for( unsigned i=0; i<sizeof(inner_work)/sizeof(int); ++i )
134         the_test.factory(inner_work[i], thread);
135 }
136 
main(int argc,char * argv[])137 int main(int argc, char* argv[]) {
138     if(argc>1) Verbose = true;
139     int DefThread = task_scheduler_init::default_num_threads();
140     MinThread = 1; MaxThread = DefThread+1;
141     ParseCommandLine( argc, argv );
142     ASSERT(MinThread <= MaxThread, 0);
143 #if INTEL_TRIAL && defined(__TBB_parallel_for_H)
144     task_scheduler_init me(MaxThread);
145 #endif
146     {
147         test_sandbox the_test("time_locked_work", StatisticsCollector::ByThreads);
148         //TODO: refactor this out as RunThreads(test&)
149         for( int t = MinThread; t < DefThread && t <= MaxThread; t *= 2)
150             RunLoops( the_test, t ); // execute undersubscribed threads
151         if( DefThread > MinThread && DefThread <= MaxThread )
152             RunLoops( the_test, DefThread ); // execute on all hw threads
153         if( DefThread < MaxThread)
154             RunLoops( the_test, MaxThread ); // execute requested oversubscribed threads
155 
156         the_test.report.SetTitle("Time of lock/unlock for mutex Name with Outer and Inner work");
157         //the_test.report.SetStatisticFormula("1AVG per size", "=AVERAGE(ROUNDS)");
158         the_test.report.Print(StatisticsCollector::HTMLFile|StatisticsCollector::ExcelXML, /*ModeName*/ "Outer work");
159     }
160     return 0;
161 }
162 
163