Changes between Version 10 and Version 11 of OpenMPTransformation
- Timestamp:
- 04/20/14 18:14:33 (12 years ago)
Legend:
- Unmodified
- Added
- Removed
- Modified
-
OpenMPTransformation
v10 v11 118 118 int _nthreads = 1+$choose_int(THREAD_MAX); 119 119 $proc _threads[_nthreads]; 120 $omp_gws _gws = $omp_gws_create($here, _nthreads); 120 121 void _thread(int _tid) { 122 $omp_ws = $omp_ws_create(_gws, _tid); 123 121 124 translate(S) 122 125 } … … 134 137 135 138 Try to determine whether the loop iterations are independent. In that case, they can all be executed by one thread. 136 137 Otherwise, iterations must be distributed among the threads in some nondeterministic way. This could blow up rapidly! Also, a thread does not have to execute its iterations in increasing order. It can execute them in any order. 138 139 Trying a few different things for now: picking a particular scheduling policy like round-robin (status with chunk size 1). Of course you can always do this if schedule is specified to be static. 140 141 The question is do we ever want to try to explore these interleavings? 142 143 Is there any loss of generality by just running all iterations concurrently? 144 145 One approach: assume you have a function or macro `CIVL_owns(n, t, i)`. It takes three ints and returns a boolean. The arguments are `n`: the number of threads; `t`: a thread ID between 0 and `n`-1 (inclusive); and `i`, an iteration index. 146 147 {{{ 139 Otherwise: 140 141 {{{ 142 // location 23: 148 143 #pragma omp parallel for 149 for (i...) 144 for (i=0; i<n; i++) 150 145 S 151 146 }}} … … 154 149 155 150 {{{ 156 for (i...) { 157 if (CIVL_owns(_nthreads, _tid, i)) { 158 translate(S) 159 } 160 } 161 barrier (unless no wait) 162 }}} 163 164 165 More general way: 166 167 {{{ 168 169 { 170 171 //use distributions 172 } 173 174 151 { 152 $int_iter iter = $omp_ws_arrive_loop(_ws, 23, 0, n-1, 1); 153 154 while ($int_iter_hasNext(iter)) { 155 int i = $int_iter_next(iter); 156 157 translate(S); 158 } 159 } 175 160 }}} 176 161 … … 181 166 182 167 {{{ 168 // location 42: 183 169 #pragma omp sections 184 { 185 #pragma omp section 186 ... 187 #pragma omp section 188 ... 189 } 190 }}} 191 192 => 193 194 {{{ 195 { 196 void section0() { 197 ... 198 } 199 void section1() { 200 ... 170 #pragma omp section 171 S0 172 #pragma omp section 173 S1 174 ... 175 }}} 176 177 => 178 179 {{{ 180 { 181 $int_iter iter = $omp_ws_arrive_sections(ws, 42); 182 183 while ($int_iter_hasNext(iter)) { 184 int _i = $int_iter_next(iter); 185 186 switch (_i) { 187 case 0: { 188 translate(S0); 189 break; 190 } 191 case 1: { 192 translate(S1); 193 break; 201 194 } 202 195 ... 203 if (CIVL_owns(_nthreads, _tid, 0) 204 section0(); 205 if (CIVL_owns(_nthreads, _tid, 1) 206 section1(); 207 ... 208 barrier unless nowait; 209 } 210 }}} 196 } 197 } 198 }}} 199 211 200 212 201 === Translating `single` === 213 202 214 Nondeterministically choose a thread, i.e, `$choose_int(threads)`. That thread executes the code, the rest skip it. 215 The question is, which thread does the choosing? The first thread to arrive at that construct? 216 217 Once again, try to determine if it matters. If the modifications and reads do not involve any private data, it doesn't matter which thread does it, so make it thread 0. 218 219 There is a barrier at the end. 203 {{{ 204 // location 33: 205 #pragma omp single 206 S 207 }}} 208 209 => 210 211 {{{ 212 if ($omp_arrive_single(ws, 33)) { 213 translate(S); 214 } 215 }}} 220 216 221 217 222 218 === Translating `barrier` === 223 219 224 Provide some system functions for this. All the threads in the team (threads[i]) register with a barrier object and partake in the barrier. Can re-use that barrier object for multiple barriers. 220 {{{ 221 // location 58: 222 #pragma omp barrier 223 }}} 224 225 => 226 227 {{{ 228 $omp_barrier_arrive(ws, 58); 229 $barrier... 230 }}} 225 231 226 232 === Translating `critical` ===
