// dot product implementation with critical region. /* OpenMP example program which computes the dot product of two arrays a and b (that is sum(a[i]*b[i]) ) using explicit synchronization with a critical region. Compile with gcc -O3 -fopenmp omp_critical.c -o omp_critical */ // Online source: http://users.abo.fi/mats/PP2012/examples/OpenMP/omp_critical.c #include #include #include #include "omp.cvh" $input int N; int main (int argc, char *argv[]) { double a[N], b[N]; double localsum, sum = 0.0; int i, tid, nthreads; /* helper variables shared by all threads*/ _Bool __critical_0 = $false; //default crticial region variable name /* parallel procedure */ void __parallel_0(int __tid) { #include "omp_thread.cvh" double i, localsum; //private(i, localsum) tid = omp_get_thread_num(); if(tid == 0) { //#pragma omp master nthreads = omp_get_num_threads(); printf("Number of threads = %d\n", nthreads); } /* The procedure of each thread for the first for loop */ void __for_0(int __tid, int __start, int __end, int __extra){ for(int __i = __start; __i < __end; __i++) { a[__i] = b[__i] = (double)__i; } if(__extra > 0) { a[__extra] = b[__extra] = (double)__extra; } } {//#pragma omp for // for (i=0; i < N; i++) // localsum = localsum + (a[i] * b[i]); int __start = __for_start(__tid, N); int __end = __for_end(__tid, N); int __extra = __for_extra(__tid, N); __for_0(__tid, __start, __end, __extra); } localsum = 0.0; /* The procedure of each thread for the second for loop */ void __for_1(int __tid, int __start, int __end, int __extra){ for(int __i = __start; __i < __end; __i++) { localsum = localsum + (a[__i] * b[__i]); } if(__extra > 0) { localsum = localsum + (a[__extra] * b[__extra]); } } {//#pragma omp for // for (i=0; i < N; i++) // localsum = localsum + (a[i] * b[i]); int __start = __for_start(__tid, N); int __end = __for_end(__tid, N); int __extra = __for_extra(__tid, N); __for_1(__tid, __start, __end, __extra); } {//#pragma omp critical $when(!__critical_0) __critical_0 = $true; sum = sum+localsum; __critical_0 = $false; } } $proc __parallel_0_procs[OMP_NUM_THREADS]; /* Create processes to conduct the parallel region */ for(i = 0; i < OMP_NUM_THREADS; i++) { __parallel_0_procs[i] = $spawn __parallel_0(i); } for(i = 0; i < OMP_NUM_THREADS; i++) { $wait(__parallel_0_procs[i]); } printf(" Sum = %f\n",sum); }