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)
5  2023, Hermann Vosseler <Ichthyostega@web.de>
6 
7   **Lumiera** is free software; you can redistribute it and/or modify it
8   under the terms of the GNU General Public License as published by the
9   Free Software Foundation; either version 2 of the License, or (at your
10   option) any later version. See the file COPYING for further details.
11 
12 * *****************************************************************/
13 
20 #include "lib/test/run.hpp"
21 #include "lib/sync-barrier.hpp"
23 #include "lib/format-cout.hpp"
24 #include "lib/sync.hpp"
25 
26 using test::Test;
27 using std::array;
28 
29 
30 namespace lib {
31 namespace test {
32 
33  namespace {// Test setup....
34 
35  const uint NUM_STAGES = 1024;
36 
42  {
43  public:
44  FakeBarrier(uint=0) { /* be happy */ }
45  void sync() { /* indulge */ }
46  };
47 
48 
54  : public Sync<NonrecursiveLock_Waitable>
55  {
56  int latch_;
57 
58  bool allPassed() { return latch_ <= 0; }
59 
60  public:
61  MonitorSync (uint nFold =2)
62  : latch_{int(nFold)}
63  { }
64 
65  void
66  sync()
67  {
68  Lock sync{this};
69  --latch_;
70  sync.wait ([this]{ return allPassed(); });
71  sync.notify_all();
72  }
73 
74  private:
75  };
76  }//(End)Test setup
77 
78 
79 
80 
81  /*******************************************************************/
92  {
93  template<class BAR, size_t nThreads>
94  double
95  performanceTest()
96  {
97  BAR barrier[NUM_STAGES];
98  for (uint i=0; i<NUM_STAGES; ++i)
99  new(&barrier[i]) BAR{nThreads};
100 
101  auto testSubject = [&](size_t i) -> size_t
102  {
103  barrier[i].sync();
104  return i; // prevent empty loop optimisation
105  };
106 
107  auto [micros, cnt] = threadBenchmark<nThreads> (testSubject, NUM_STAGES);
108  CHECK (cnt == nThreads * NUM_STAGES*(NUM_STAGES-1)/2);
109  return micros;
110  }
111 
112 
113 
136  virtual void
137  run (Arg)
138  {
139  cout<<"\n\n■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■"<<endl;
140 
141  double time_yieldWait_80 = performanceTest<SyncBarrier, 80>();
142  double time_yieldWait_64 = performanceTest<SyncBarrier, 64>();
143  double time_yieldWait_48 = performanceTest<SyncBarrier, 48>();
144  double time_yieldWait_32 = performanceTest<SyncBarrier, 32>();
145  double time_yieldWait_16 = performanceTest<SyncBarrier, 16>();
146  double time_yieldWait_8 = performanceTest<SyncBarrier, 8>();
147  double time_yieldWait_4 = performanceTest<SyncBarrier, 4>();
148  double time_yieldWait_2 = performanceTest<SyncBarrier, 2>();
149  //
150  double time_emptySetup = performanceTest<FakeBarrier, 5>();
151  //
152  double time_sleepWait_16 = performanceTest<MonitorSync, 16>();
153  double time_sleepWait_8 = performanceTest<MonitorSync, 8>();
154  double time_sleepWait_4 = performanceTest<MonitorSync, 4>();
155  double time_sleepWait_2 = performanceTest<MonitorSync, 2>();
156 
157  cout<<"\n___Microbenchmark_______ (µs)"
158  <<"\nemptySetup : "<<time_emptySetup
159  <<"\n : "
160  <<"\nSyncBarrier (2 Thr) : "<<time_yieldWait_2
161  <<"\nSyncBarrier (4 Thr) : "<<time_yieldWait_4
162  <<"\nSyncBarrier (8 Thr) : "<<time_yieldWait_8
163  <<"\nSyncBarrier (16 Thr) : "<<time_yieldWait_16
164  <<"\nSyncBarrier (32 Thr) : "<<time_yieldWait_32
165  <<"\nSyncBarrier (48 Thr) : "<<time_yieldWait_48
166  <<"\nSyncBarrier (64 Thr) : "<<time_yieldWait_64
167  <<"\nSyncBarrier (80 Thr) : "<<time_yieldWait_80
168  <<"\n : "
169  <<"\nMonitorWait (2 Thr) : "<<time_sleepWait_2
170  <<"\nMonitorWait (4 Thr) : "<<time_sleepWait_4
171  <<"\nMonitorWait (8 Thr) : "<<time_sleepWait_8
172  <<"\nMonitorWait (16 Thr) : "<<time_sleepWait_16
173  <<"\n________________________\n"
174  <<"\nbarriers..... "<<NUM_STAGES
175  <<endl;
176 
177  // Unable to assert more than a sanity check here....
178  CHECK (time_emptySetup < time_yieldWait_4);
179  }
180  };
181 
182 
183 
185  LAUNCHER (SyncBarrierPerformance_test, "function common");
186 
187 
188 
189 }} // namespace lib::test
Facility for monitor object based locking.
Definition: sync.hpp:209
Automatically use custom string conversion in C++ stream output.
Definition: run.hpp:40
scoped guard to control the actual locking.
Definition: sync.hpp:226
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:53
Simplistic 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.