taskbench.c (8372B)
1 /**************************************************************************** 2 * * 3 * OpenMP MicroBenchmark Suite - Version 3.1 * 4 * * 5 * produced by * 6 * * 7 * Mark Bull, Fiona Reid and Nix Mc Donnell * 8 * * 9 * at * 10 * * 11 * Edinburgh Parallel Computing Centre * 12 * * 13 * email: markb@epcc.ed.ac.uk or fiona@epcc.ed.ac.uk * 14 * * 15 * * 16 * This version copyright (c) The University of Edinburgh, 2015. * 17 * * 18 * * 19 * Licensed under the Apache License, Version 2.0 (the "License"); * 20 * you may not use this file except in compliance with the License. * 21 * You may obtain a copy of the License at * 22 * * 23 * http://www.apache.org/licenses/LICENSE-2.0 * 24 * * 25 * Unless required by applicable law or agreed to in writing, software * 26 * distributed under the License is distributed on an "AS IS" BASIS, * 27 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * 28 * See the License for the specific language governing permissions and * 29 * limitations under the License. * 30 * * 31 ****************************************************************************/ 32 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <omp.h> 36 37 #include "common.h" 38 #include "taskbench.h" 39 40 #define DEPTH 6 41 42 int main(int argc, char **argv) { 43 44 init(argc, argv); 45 46 #ifdef OMPVER3 47 48 /* GENERATE REFERENCE TIME */ 49 reference("reference time 1", &refer); 50 51 /* TEST PARALLEL TASK GENERATION */ 52 benchmark("PARALLEL TASK", &testParallelTaskGeneration); 53 54 /* TEST MASTER TASK GENERATION */ 55 benchmark("MASTER TASK", &testMasterTaskGeneration); 56 57 /* TEST MASTER TASK GENERATION WITH BUSY SLAVES */ 58 benchmark("MASTER TASK BUSY SLAVES", &testMasterTaskGenerationWithBusySlaves); 59 60 /* TEST CONDITIONAL TASK GENERATION */ 61 #ifndef DISABLE_CONDITIONAL_TASK_TEST 62 benchmark("CONDITIONAL TASK", &testConditionalTaskGeneration); 63 #endif // DISABLE_CONDITIONAL_TASK_TEST 64 65 /* TEST TASK WAIT */ 66 benchmark("TASK WAIT", &testTaskWait); 67 68 /* TEST TASK BARRIER */ 69 #ifndef DISABLE_BARRIER_TEST 70 benchmark("TASK BARRIER", &testTaskBarrier); 71 #endif //DISABLE_BARRIER_TEST 72 73 #ifndef DISABLE_NESTED_TASKS_TESTS 74 /* TEST NESTED TASK GENERATION */ 75 benchmark("NESTED TASK", &testNestedTaskGeneration); 76 77 /* TEST NESTED MASTER TASK GENERATION */ 78 benchmark("NESTED MASTER TASK", &testNestedMasterTaskGeneration); 79 80 #endif // DISABLE_NESTED_TASKS_TESTS 81 82 /* GENERATE THE SECOND REFERENCE TIME */ 83 reference("reference time 2", &refer); 84 85 /* TEST BRANCH TASK TREE */ 86 benchmark("BRANCH TASK TREE", &testBranchTaskGeneration); 87 88 /* TEST LEAF TASK TREE */ 89 benchmark("LEAF TASK TREE", &testLeafTaskGeneration); 90 91 #endif // OMPVER3 92 93 finalise(); 94 95 return EXIT_SUCCESS; 96 97 } 98 99 /* Calculate the reference time. */ 100 void refer() { 101 int j; 102 for (j = 0; j < innerreps; j++) { 103 delay(delaylength); 104 } 105 106 } 107 108 /* Calculate the second reference time. */ 109 void refer2() { 110 int j; 111 for (j = 0; j < (innerreps >> DEPTH) * (1 << DEPTH); j++) { 112 delay(delaylength); 113 }; 114 115 } 116 117 /* Test parallel task generation overhead */ 118 void testParallelTaskGeneration() { 119 int j; 120 #pragma omp parallel private( j ) 121 { 122 for ( j = 0; j < innerreps; j ++ ) { 123 #pragma omp task 124 { 125 delay( delaylength ); 126 127 } // task 128 }; // for j 129 } // parallel 130 131 } 132 133 /* Test master task generation overhead */ 134 void testMasterTaskGeneration() { 135 int j; 136 #pragma omp parallel private(j) 137 { 138 #pragma omp master 139 { 140 /* Since this is executed by one thread we need innerreps * nthreads 141 iterations */ 142 for (j = 0; j < innerreps * nthreads; j++) { 143 #pragma omp task 144 { 145 delay(delaylength); 146 147 } 148 149 } /* End for j */ 150 } /* End master */ 151 } /* End parallel */ 152 153 } 154 155 /* Test master task generation overhead when the slave threads are busy */ 156 void testMasterTaskGenerationWithBusySlaves() { 157 int j; 158 #pragma omp parallel private( j ) 159 { 160 int thread_num = omp_get_thread_num(); 161 for (j = 0; j < innerreps; j ++ ) { 162 163 if ( thread_num == 0 ) { 164 #pragma omp task 165 { 166 delay( delaylength ); 167 } // task 168 169 } else { 170 delay( delaylength ); 171 172 }; // if 173 }; // for j 174 } // parallel 175 } 176 177 /* Measure overhead of checking if a task should be spawned. */ 178 void testConditionalTaskGeneration() { 179 int j; 180 #pragma omp parallel private(j) 181 { 182 for (j = 0; j < innerreps; j++) { 183 #pragma omp task if(returnfalse()) 184 { 185 delay( delaylength ); 186 } 187 } 188 } 189 } 190 191 #ifndef DISABLE_NESTED_TASKS_TESTS 192 193 /* Measure overhead of nested tasks (all threads construct outer tasks) */ 194 void testNestedTaskGeneration() { 195 int i,j; 196 #pragma omp parallel private( i, j ) 197 { 198 for ( j = 0; j < innerreps / nthreads; j ++ ) { 199 #pragma omp task private( i ) 200 { 201 for ( i = 0; i < nthreads; i ++ ) { 202 #pragma omp task untied 203 { 204 delay( delaylength ); 205 206 } // task 207 }; // for i 208 209 // wait for inner tasks to complete 210 #pragma omp taskwait 211 212 } // task 213 }; // for j 214 } // parallel 215 } 216 217 /* Measure overhead of nested tasks (master thread constructs outer tasks) */ 218 void testNestedMasterTaskGeneration() { 219 int i, j; 220 #pragma omp parallel private( i, j ) 221 { 222 #pragma omp master 223 { 224 for ( j = 0; j < innerreps; j ++ ) { 225 #pragma omp task private( i ) 226 { 227 for ( i = 0; i < nthreads; i ++ ) { 228 #pragma omp task 229 { 230 delay( delaylength ); 231 232 } // task 233 }; // for i 234 235 // wait for inner tasks to complete 236 #pragma omp taskwait 237 238 } // task 239 }; // for j 240 } // master 241 } // parallel 242 } 243 #endif // DISABLE_NESTED_TASKS_TESTS 244 245 /* Measure overhead of taskwait (all threads construct tasks) */ 246 void testTaskWait() { 247 int j; 248 #pragma omp parallel private( j ) 249 { 250 for ( j = 0; j < innerreps; j ++ ) { 251 #pragma omp task 252 { 253 delay( delaylength ); 254 255 } // task 256 #pragma omp taskwait 257 258 }; // for j 259 } // parallel 260 } 261 262 /* Measure overhead of tasking barrier (all threads construct tasks) */ 263 void testTaskBarrier() { 264 int j; 265 #pragma omp parallel private( j ) 266 { 267 for ( j = 0; j < innerreps; j ++ ) { 268 #pragma omp task 269 { 270 delay( delaylength ); 271 272 } // task 273 #pragma omp barrier 274 275 }; // for j 276 } // parallel 277 } 278 279 /* Test parallel task generation overhead where work is done at all levels. */ 280 void testBranchTaskGeneration() { 281 int j; 282 #pragma omp parallel private(j) 283 { 284 for (j = 0; j < (innerreps >> DEPTH); j++) { 285 #pragma omp task 286 { 287 branchTaskTree(DEPTH); 288 delay(delaylength); 289 } 290 291 } 292 } 293 } 294 295 void branchTaskTree(int tree_level) { 296 if ( tree_level > 0 ) { 297 #pragma omp task 298 { 299 branchTaskTree(tree_level - 1); 300 branchTaskTree(tree_level - 1); 301 delay(delaylength); 302 } 303 } 304 } 305 306 /* Test parallel task generation overhead where work is done only at the leaf level. */ 307 void testLeafTaskGeneration() { 308 int j; 309 #pragma omp parallel private(j) 310 { 311 for (j = 0; j < (innerreps >> DEPTH); j++) { 312 leafTaskTree(DEPTH); 313 314 } 315 } 316 317 } 318 319 void leafTaskTree(int tree_level) { 320 if ( tree_level == 0 ) { 321 delay(delaylength); 322 323 } else { 324 #pragma omp task 325 { 326 leafTaskTree(tree_level - 1); 327 leafTaskTree(tree_level - 1); 328 } 329 } 330 } 331