Lumiera  0.pre.03
»edit your freedom«
sync-barrier-performance-test.cpp
Go to the documentation of this file.
1 /*
2  SyncBarrierPerformance(Test) - investigate performance of yield-waiting synchronisation
3 
4  Copyright (C) Lumiera.org
5  2023, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 * *****************************************************/
22 
29 #include "lib/test/run.hpp"
30 #include "lib/sync-barrier.hpp"
32 #include "lib/format-cout.hpp"
33 #include "lib/sync.hpp"
34 
35 using test::Test;
36 using std::array;
37 
38 
39 namespace lib {
40 namespace test {
41 
42  namespace {// Test setup....
43 
44  const uint NUM_STAGES = 1024;
45 
51  {
52  public:
53  FakeBarrier(uint=0) { /* be happy */ }
54  void sync() { /* indulge */ }
55  };
56 
57 
63  : public Sync<NonrecursiveLock_Waitable>
64  {
65  int latch_;
66 
67  bool allPassed() { return latch_ <= 0; }
68 
69  public:
70  MonitorSync (uint nFold =2)
71  : latch_{int(nFold)}
72  { }
73 
74  void
75  sync()
76  {
77  Lock sync{this};
78  --latch_;
79  sync.wait ([this]{ return allPassed(); });
80  sync.notify_all();
81  }
82 
83  private:
84  };
85  }//(End)Test setup
86 
87 
88 
89 
90  /*******************************************************************/
101  {
102  template<class BAR, size_t nThreads>
103  double
104  performanceTest()
105  {
106  BAR barrier[NUM_STAGES];
107  for (uint i=0; i<NUM_STAGES; ++i)
108  new(&barrier[i]) BAR{nThreads};
109 
110  auto testSubject = [&](size_t i) -> size_t
111  {
112  barrier[i].sync();
113  return i; // prevent empty loop optimisation
114  };
115 
116  auto [micros, cnt] = threadBenchmark<nThreads> (testSubject, NUM_STAGES);
117  CHECK (cnt == nThreads * NUM_STAGES*(NUM_STAGES-1)/2);
118  return micros;
119  }
120 
121 
122 
145  virtual void
146  run (Arg)
147  {
148  cout<<"\n\n■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■"<<endl;
149 
150  double time_yieldWait_80 = performanceTest<SyncBarrier, 80>();
151  double time_yieldWait_64 = performanceTest<SyncBarrier, 64>();
152  double time_yieldWait_48 = performanceTest<SyncBarrier, 48>();
153  double time_yieldWait_32 = performanceTest<SyncBarrier, 32>();
154  double time_yieldWait_16 = performanceTest<SyncBarrier, 16>();
155  double time_yieldWait_8 = performanceTest<SyncBarrier, 8>();
156  double time_yieldWait_4 = performanceTest<SyncBarrier, 4>();
157  double time_yieldWait_2 = performanceTest<SyncBarrier, 2>();
158  //
159  double time_emptySetup = performanceTest<FakeBarrier, 5>();
160  //
161  double time_sleepWait_16 = performanceTest<MonitorSync, 16>();
162  double time_sleepWait_8 = performanceTest<MonitorSync, 8>();
163  double time_sleepWait_4 = performanceTest<MonitorSync, 4>();
164  double time_sleepWait_2 = performanceTest<MonitorSync, 2>();
165 
166  cout<<"\n___Microbenchmark_______ (µs)"
167  <<"\nemptySetup : "<<time_emptySetup
168  <<"\n : "
169  <<"\nSyncBarrier (2 Thr) : "<<time_yieldWait_2
170  <<"\nSyncBarrier (4 Thr) : "<<time_yieldWait_4
171  <<"\nSyncBarrier (8 Thr) : "<<time_yieldWait_8
172  <<"\nSyncBarrier (16 Thr) : "<<time_yieldWait_16
173  <<"\nSyncBarrier (32 Thr) : "<<time_yieldWait_32
174  <<"\nSyncBarrier (48 Thr) : "<<time_yieldWait_48
175  <<"\nSyncBarrier (64 Thr) : "<<time_yieldWait_64
176  <<"\nSyncBarrier (80 Thr) : "<<time_yieldWait_80
177  <<"\n : "
178  <<"\nMonitorWait (2 Thr) : "<<time_sleepWait_2
179  <<"\nMonitorWait (4 Thr) : "<<time_sleepWait_4
180  <<"\nMonitorWait (8 Thr) : "<<time_sleepWait_8
181  <<"\nMonitorWait (16 Thr) : "<<time_sleepWait_16
182  <<"\n________________________\n"
183  <<"\nbarriers..... "<<NUM_STAGES
184  <<endl;
185 
186  // Unable to assert more than a sanity check here....
187  CHECK (time_emptySetup < time_yieldWait_4);
188  }
189  };
190 
191 
192 
194  LAUNCHER (SyncBarrierPerformance_test, "function common");
195 
196 
197 
198 }} // namespace lib::test
Facility for monitor object based locking.
Definition: sync.hpp:217
Automatically use custom string conversion in C++ stream output.
Definition: run.hpp:49
scoped guard to control the actual locking.
Definition: sync.hpp:234
Functions to perform (multithreaded) timing measurement on a given functor.
Implementation namespace for support and library code.
Object Monitor based synchronisation.
Abstract Base Class for all testcases.
Definition: run.hpp:62
Simple test class runner.
A Monitor based reference implementation, using Mutex + Condition Variable for sleeping wait...
A N-fold synchronisation latch using yield-wait until fulfilment.