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