1 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <omp.h> 5 6 int main(int argc, char * argv[]) { 7 8 int x; // the variable to increment 9 int count; // the number of times each variable will increment x 10 int nThreads; // the number of threads to use 11 int i; // a loop counter 12 omp_lock_t lock; // a traditional lock 13 14 // the argument stream should look like this: 15 // increment <count> <nThreads> 16 if(argc!=3) { 17 fprintf(stderr,"Usage:\n%s <count> <nThreads>\n",argv[0]); 18 exit(1); 19 } 20 21 count = atoi(argv[1]); 22 nThreads = atoi(argv[2]); 23 24 if(count<=0 || nThreads <=0) { 25 fprintf(stderr,"Count and nThreads must be >0\n"); 26 exit(1); 27 } 28 29 // arguments parsed successfully 30 // now start incrementing 31 omp_set_num_threads(nThreads); 32 x = 0; 33 34 // must call this if you use locks... 35 omp_init_lock(&lock); 36 37 // fork a team of threads 38 #pragma omp parallel \ 39 private(i) \ 40 shared(x,count) 41 { 42 43 for(i=0;i<count;i++) { 44 // use critical section construct to increment 45 #pragma omp critical 46 { 47 // each thread will execute here, but one-at-a-time 48 x++; 49 50 } // end of critical section 51 } 52 53 // wait for all threads to finish incrementing 54 #pragma omp barrier 55 56 #pragma omp master 57 { 58 // only the master thread will execute here (thread id = 0) 59 fprintf(stdout,"Master thread (id=%i) reports x=%i\n", 60 omp_get_thread_num(), 61 x); 62 x = 0; 63 } 64 65 // wait for the master to print and then reset x 66 #pragma omp barrier 67 68 // now update x using ATOMIC directive 69 for(i=0;i<count;i++) { 70 #pragma omp atomic 71 x++; 72 } 73 74 // ensure all threads have done the update 75 #pragma omp barrier 76 77 #pragma omp single 78 { 79 // use of Single means ANY thread may enter, but only one 80 fprintf(stdout," Thread %i reports x=%i\n", 81 omp_get_thread_num(), 82 x); 83 x = 0; 84 85 } 86 87 // ensure all threads wait for printing and reset before continue 88 #pragma omp barrier 89 90 // each thread will now loop, acquiring and releasing the 91 // omp lock 92 for(i=0;i<count;i++) { 93 omp_set_lock(&lock); 94 // this thread now has the lock 95 x++; 96 97 // memory must remain consistent -- why? 98 // Answer: ATOMIC and CRITICAL have built-in flush! 99 // #pragma omp flush 100 101 omp_unset_lock(&lock); // don't forget to unlock 102 } 103 104 #pragma omp barrier 105 106 #pragma omp single 107 { 108 109 110 // done with the lock 111 omp_destroy_lock(&lock); 112 fprintf(stdout," Thread %i reports x=%i\n", 113 omp_get_thread_num(), 114 x); 115 116 } 117 } // JOIN occurs here, with an implicit barrier 118 // end of Parallel 119 120 exit(0); 121 } 122