| 1 | /*
|
|---|
| 2 | OpenMP example program that computes the value of Pi using the trapeziod rule.
|
|---|
| 3 | Compile with gcc -fopenmp -O3 omp_pi.c -o omp_pi
|
|---|
| 4 | */
|
|---|
| 5 | // Online source: http://users.abo.fi/mats/PP2012/examples/OpenMP/omp_pi.c
|
|---|
| 6 | // // permission obtained
|
|---|
| 7 | #include <omp.h>
|
|---|
| 8 | #include <stdio.h>
|
|---|
| 9 | #include <stdlib.h>
|
|---|
| 10 | #include <math.h>
|
|---|
| 11 | #include <assert.h>
|
|---|
| 12 |
|
|---|
| 13 | #ifdef _CIVL
|
|---|
| 14 | $input int N=100;
|
|---|
| 15 | #else
|
|---|
| 16 | #define N 1000
|
|---|
| 17 | #endif
|
|---|
| 18 |
|
|---|
| 19 | void print_usage(char *s) {
|
|---|
| 20 | printf("Usage: %s -i <nr of intervals>\n", s);
|
|---|
| 21 | exit(0);
|
|---|
| 22 | }
|
|---|
| 23 |
|
|---|
| 24 | /* This is the function to integrate */
|
|---|
| 25 | double f(double x) {
|
|---|
| 26 | return (4.0 / (1.0 + x*x));
|
|---|
| 27 | }
|
|---|
| 28 |
|
|---|
| 29 | int main (int argc, char *argv[]) {
|
|---|
| 30 |
|
|---|
| 31 | const double PI24 = 3.141592653589793238462643;
|
|---|
| 32 | int nthreads, tid;
|
|---|
| 33 | double d, x, sum=0.0, pi;
|
|---|
| 34 | double starttime, stoptime;
|
|---|
| 35 | int n=N, i;
|
|---|
| 36 | char c;
|
|---|
| 37 |
|
|---|
| 38 | #ifndef _CIVL
|
|---|
| 39 | /* Check if we have at least one argument */
|
|---|
| 40 | if (argc <=1 ) {
|
|---|
| 41 | print_usage(argv[0]);
|
|---|
| 42 | }
|
|---|
| 43 | else {
|
|---|
| 44 | /* Parse the arguments for a -h or -i flag */
|
|---|
| 45 | while ((c=getopt(argc, argv, "hi:")) != EOF) {
|
|---|
| 46 | switch (c) {
|
|---|
| 47 | case 'h':
|
|---|
| 48 | print_usage(argv[0]);
|
|---|
| 49 | case 'i':
|
|---|
| 50 | n = atoi(optarg); /* Get number of intervals */
|
|---|
| 51 | break;
|
|---|
| 52 | default:
|
|---|
| 53 | print_usage(argv[0]);
|
|---|
| 54 | }
|
|---|
| 55 | }
|
|---|
| 56 | }
|
|---|
| 57 | #endif
|
|---|
| 58 |
|
|---|
| 59 |
|
|---|
| 60 | /* Compute the size of intervals */
|
|---|
| 61 | d = 1.0/(double) n;
|
|---|
| 62 |
|
|---|
| 63 | /* Start the threads */
|
|---|
| 64 | #pragma omp parallel default(shared) private(nthreads, tid, x)
|
|---|
| 65 | {
|
|---|
| 66 | /* Get the thread number */
|
|---|
| 67 | tid = omp_get_thread_num();
|
|---|
| 68 |
|
|---|
| 69 | /* The master thread checks how many there are */
|
|---|
| 70 | #pragma omp master
|
|---|
| 71 | {
|
|---|
| 72 | nthreads = omp_get_num_threads();
|
|---|
| 73 | printf("Number of threads = %d\n", nthreads);
|
|---|
| 74 | starttime = omp_get_wtime(); /* Measure the execution time */
|
|---|
| 75 | }
|
|---|
| 76 |
|
|---|
| 77 | /* This loop is executed in parallel by the threads */
|
|---|
| 78 | #pragma omp for reduction(+:sum)
|
|---|
| 79 | for (i=0; i<n; i++) {
|
|---|
| 80 | x = d*(double)i;
|
|---|
| 81 | sum += f(x) + f(x+d);
|
|---|
| 82 | }
|
|---|
| 83 | } /* The parallel section ends here */
|
|---|
| 84 |
|
|---|
| 85 | /* The multiplication by d and division by 2 is moved out of the loop */
|
|---|
| 86 | pi = d*sum*0.5;
|
|---|
| 87 |
|
|---|
| 88 | stoptime = omp_get_wtime();
|
|---|
| 89 | printf("The computed value of Pi is %2.24f\n", pi);
|
|---|
| 90 | printf("The \"exact\" value of Pi is %2.24f\n", PI24);
|
|---|
| 91 | printf("The difference is %e\n", fabs(PI24-pi));
|
|---|
| 92 | #ifdef _CIVL
|
|---|
| 93 | assert(fabs(PI24-pi) < 0.1);
|
|---|
| 94 | #endif
|
|---|
| 95 | printf("Time: %2.4f seconds \n", stoptime-starttime);
|
|---|
| 96 |
|
|---|
| 97 | exit(0);
|
|---|
| 98 | }
|
|---|