source: doc/theses/thierry_delisle_PhD/code/processor_list_fast.cpp@ 50aeb6f

ADT arm-eh ast-experimental enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr pthread-emulation qualifiedEnum
Last change on this file since 50aeb6f was 50aeb6f, checked in by Thierry Delisle <tdelisle@…>, 6 years ago

Small tweaks to the memory layout

  • Property mode set to 100644
File size: 3.9 KB
Line 
1#include "processor_list.hpp"
2
3#include <array>
4#include <iomanip>
5#include <iostream>
6#include <locale>
7#include <string>
8#include <thread>
9
10#include "utils.hpp"
11
12unsigned num() {
13 return 0x1000000;
14}
15
16//-------------------
17
18struct processor {
19 unsigned id;
20};
21void run(unsigned nthread, double duration, unsigned writes, unsigned epochs) {
22 assert(writes < 100);
23
24 // List being tested
25 processor_list list = {};
26
27 // Barrier for synchronization
28 barrier_t barrier(nthread + 1);
29
30 // Data to check everything is OK
31 size_t write_committed = 0ul;
32 struct {
33 std::atomic_size_t write = { 0ul };
34 std::atomic_size_t read = { 0ul };
35 std::atomic_size_t epoch = { 0ul };
36 } lock_cnt;
37
38 // Flag to signal termination
39 std::atomic_bool done = { false };
40
41 std::thread * threads[nthread];
42 unsigned i = 1;
43 for(auto & t : threads) {
44 t = new std::thread([&done, &list, &barrier, &write_committed, &lock_cnt, writes, epochs](unsigned tid) {
45 Random rand(tid + rdtscl());
46 processor proc;
47 proc.id = list.doregister(&proc);
48 size_t writes_cnt = 0;
49 size_t reads_cnt = 0;
50 size_t epoch_cnt = 0;
51
52 affinity(tid);
53
54 barrier.wait(tid);
55
56 while(__builtin_expect(!done, true)) {
57 auto r = rand.next() % 100;
58 if (r < writes) {
59 auto n = list.write_lock();
60 write_committed++;
61 writes_cnt++;
62 assert(writes_cnt < -2ul);
63 list.write_unlock(n);
64 }
65 else if(r < epochs) {
66 list.epoch_check();
67 epoch_cnt++;
68 }
69 else {
70 list.read_lock(proc.id);
71 reads_cnt++;
72 assert(reads_cnt < -2ul);
73 list.read_unlock(proc.id);
74 }
75 }
76
77 barrier.wait(tid);
78
79 auto p = list.unregister(proc.id);
80 assert(&proc == p);
81 lock_cnt.write += writes_cnt;
82 lock_cnt.read += reads_cnt;
83 lock_cnt.epoch += epoch_cnt;
84 }, i++);
85 }
86
87 auto before = Clock::now();
88 barrier.wait(0);
89
90 while(true) {
91 usleep(1000);
92 auto now = Clock::now();
93 duration_t durr = now - before;
94 if( durr.count() > duration ) {
95 done = true;
96 break;
97 }
98 }
99
100 barrier.wait(0);
101 auto after = Clock::now();
102 duration_t durr = after - before;
103 duration = durr.count();
104
105 for(auto t : threads) {
106 t->join();
107 delete t;
108 }
109
110 assert(write_committed == lock_cnt.write);
111
112 size_t totalop = lock_cnt.read + lock_cnt.write + lock_cnt.epoch;
113 size_t ops_sec = size_t(double(totalop) / duration);
114 size_t ops_thread = ops_sec / nthread;
115 double dur_nano = duration_cast<std::nano>(1.0);
116
117 std::cout << "Duration : " << duration << "s\n";
118 std::cout << "Total ops : " << totalop << "(" << lock_cnt.read << "r, " << lock_cnt.write << "w, " << lock_cnt.epoch << "e)\n";
119 std::cout << "Ops/sec : " << ops_sec << "\n";
120 std::cout << "Ops/sec/thread: " << ops_thread << "\n";
121 std::cout << "ns/Op : " << ( dur_nano / ops_thread )<< "\n";
122}
123
124void usage(char * argv[]) {
125 std::cerr << argv[0] << ": [DURATION (FLOAT:SEC)] [NTHREADS] [%WRITES]" << std::endl;;
126 std::exit(1);
127}
128
129int main(int argc, char * argv[]) {
130
131 double duration = 5.0;
132 unsigned nthreads = 2;
133 unsigned writes = 0;
134 unsigned epochs = 0;
135
136 std::cout.imbue(std::locale(""));
137
138 switch (argc)
139 {
140 case 5:
141 epochs = std::stoul(argv[4]);
142 [[fallthrough]];
143 case 4:
144 writes = std::stoul(argv[3]);
145 if( (writes + epochs) > 100 ) {
146 std::cerr << "Writes + Epochs must be valid percentage, was " << argv[3] << " + " << argv[4] << "(" << writes << " + " << epochs << ")" << std::endl;
147 usage(argv);
148 }
149 [[fallthrough]];
150 case 3:
151 nthreads = std::stoul(argv[2]);
152 [[fallthrough]];
153 case 2:
154 duration = std::stod(argv[1]);
155 if( duration <= 0.0 ) {
156 std::cerr << "Duration must be positive, was " << argv[1] << "(" << duration << ")" << std::endl;
157 usage(argv);
158 }
159 [[fallthrough]];
160 case 1:
161 break;
162 default:
163 usage(argv);
164 break;
165 }
166
167 check_cache_line_size();
168
169 std::cout << "Running " << nthreads << " threads for " << duration << " seconds with " << writes << "% writes and " << epochs << "% epochs" << std::endl;
170 run(nthreads, duration, writes, epochs + writes);
171
172 return 0;
173}
Note: See TracBrowser for help on using the repository browser.