source: benchmark/readyQ/transfer.cfa @ eeb9f9f

ADTarm-ehast-experimentalenumforall-pointer-decayjacob/cs343-translationnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since eeb9f9f was b374dbc, checked in by Thierry Delisle <tdelisle@…>, 4 years ago

Added cforall test for fairness.

  • 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
16$thread * 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.