source: benchmark/readyQ/transfer.cfa@ f93d7fc

ADT ast-experimental enum forall-pointer-decay jacob/cs343-translation pthread-emulation qualifiedEnum
Last change on this file since f93d7fc was e49b6f5, checked in by Thierry Delisle <tdelisle@…>, 4 years ago

Missed some benchmarks.

  • Property mode set to 100644
File size: 3.3 KB
Line 
1#include "rq_bench.hfa"
2#include <fstream.hfa>
3
4Duration default_preemption() {
5 return 0;
6}
7
8#define PRINT(...)
9
10__lehmer64_state_t lead_seed;
11volatile unsigned leader;
12volatile size_t lead_idx;
13
14bool exhaust = false;
15
16thread$ * the_main;
17
18thread __attribute__((aligned(128))) MyThread {
19 unsigned id;
20 volatile size_t idx;
21 bench_sem sem;
22 size_t rechecks;
23};
24
25void ?{}( MyThread & this, unsigned id ) {
26 ((thread&)this){ bench_cluster };
27 this.id = id;
28 this.idx = 0;
29 this.rechecks = 0;
30}
31
32MyThread ** threads;
33
34static void waitgroup() {
35 Time start = timeHiRes();
36 for(i; nthreads) {
37 PRINT( sout | "Waiting for :" | i | "(" | threads[i]->idx | ")"; )
38 while( threads[i]->idx != lead_idx ) {
39 Pause();
40 if( (timeHiRes() - start) > 5`s ) {
41 serr | "Programs has been blocked for more than 5 secs";
42 exit(1);
43 }
44 }
45 }
46 PRINT( sout | "Waiting done"; )
47}
48
49static void wakegroup(unsigned me) {
50 if(!exhaust) return;
51
52 for(i; nthreads) {
53 if(i!= me) post( threads[i]->sem );
54 }
55}
56
57static void lead(MyThread & this) {
58 this.idx = ++lead_idx;
59 if(lead_idx > stop_count) {
60 PRINT( sout | "Leader" | this.id | "done"; )
61 unpark( the_main );
62 return;
63 }
64
65 PRINT( sout | "Leader no" | this.idx| ":" | this.id; )
66
67 waitgroup();
68
69 unsigned nleader = __lehmer64( lead_seed ) % nthreads;
70 __atomic_store_n( &leader, nleader, __ATOMIC_SEQ_CST );
71
72 wakegroup(this.id);
73}
74
75static void wait(MyThread & this) {
76 yield();
77 if(lead_idx == this.idx) {
78 this.rechecks++;
79 return;
80 }
81
82 assert( (lead_idx - 1) == this.idx );
83 __atomic_add_fetch( &this.idx, 1, __ATOMIC_SEQ_CST );
84 if(exhaust) wait( this.sem );
85 else yield();
86}
87
88void main(MyThread & this) {
89 park();
90
91 unsigned me = this.id;
92
93 for() {
94 if(leader == me) {
95 lead( this );
96 }
97 else {
98 wait( this );
99 }
100 if(lead_idx > stop_count) break;
101 }
102}
103
104// ==================================================
105int main(int argc, char * argv[]) {
106 __lehmer64_state_t lead_seed = getpid();
107 for(10) __lehmer64( lead_seed );
108 unsigned nprocs = 2;
109
110 cfa_option opt[] = {
111 BENCH_OPT,
112 { 'e', "exhaust", "Whether or not threads that have seen the new epoch should yield or park.", exhaust, parse_yesno}
113 };
114 BENCH_OPT_PARSE("cforall transition benchmark");
115
116 if(clock_mode) {
117 serr | "This benchmark doesn't support duration mode";
118 return 1;
119 }
120
121 if(nprocs < 2) {
122 serr | "Must have at least 2 processors";
123 return 1;
124 }
125
126 lead_idx = 0;
127 leader = __lehmer64( lead_seed ) % nthreads;
128
129 size_t rechecks = 0;
130 the_main = active_thread();
131
132 Time start, end;
133 {
134 BenchCluster bc = { nprocs };
135 {
136 threads = alloc(nthreads);
137 for(i; nthreads) {
138 threads[i] = malloc();
139 (*threads[i]){
140 i
141 };
142 }
143
144 start = timeHiRes();
145 for(i; nthreads) {
146 unpark(*threads[i]);
147 }
148
149 park();
150 end = timeHiRes();
151
152 for(i; nthreads) {
153 post(threads[i]->sem);
154 }
155
156 for(i; nthreads) {
157 MyThread & thrd = join(*threads[i]);
158 PRINT( sout | i | "joined"; )
159 rechecks += thrd.rechecks;
160 ^( *threads[i] ){};
161 free(threads[i]);
162 }
163
164 free(threads);
165 }
166 }
167
168 sout | "Duration : " | ws(3, 3, unit(eng((end - start)`ds))) | 's';
169 sout | "Number of processors : " | nprocs;
170 sout | "Number of threads : " | nthreads;
171 sout | "Total Operations(ops) : " | stop_count;
172 sout | "Threads parking on wait : " | (exhaust ? "yes" : "no");
173 sout | "Rechecking : " | rechecks;
174
175
176}
Note: See TracBrowser for help on using the repository browser.