/* * compute pi by integrating f(x) = 4/(1 + x*x) * example program for colloq * pthread version */ #include <stdio.h> #include <stdlib.h> #include <math.h> #include <pthread.h> #define DEF_N 100 /* default arry dimension */ #define DEF_NTHREADS 4 /* default number of threads */ typedef struct { int nthreads; /* number of threads */ int myid; /* id of thread (0 .. nthreads-1) */ int n; /* total number of points */ double h; /* step size */ double *localsum; /* array with results */ } thread_arg_t; void * par_loop(void * id); #define PI25DT 3.141592653589793238462643 void main(int argc, char *argv[]) { double h, sum, pi; int n, i; double * localsum; /* partial results */ int nthreads; /* number of threads */ pthread_t * thread_id; /* ids of all threads */ thread_arg_t * thread_arg; /* arguments for the threads */ /* get command line arguments */ if (argc != 3) { printf("Using default values!\n"); n = DEF_N; nthreads = DEF_NTHREADS; } else { n = atoi(argv[1]); nthreads = atoi(argv[2]); } /* initialize data */ thread_id = (pthread_t *) malloc(nthreads * sizeof(pthread_t)); thread_arg = (thread_arg_t *) malloc(nthreads * sizeof(thread_arg_t)); localsum = (double *) malloc(nthreads * sizeof(double)); /* compute arguments for all threads */ h = 1.0/n; for (i=0; i<nthreads; i++) { thread_arg[i].nthreads = nthreads; thread_arg[i].myid = i; thread_arg[i].n = n; thread_arg[i].h = h; thread_arg[i].localsum = localsum; } /* create threads, which all call par_loop */ for (i=1; i<nthreads; i++) { pthread_create(&thread_id[i], NULL, par_loop, &thread_arg[i]); } /* work myself, as thread 0 */ par_loop(&thread_arg[0]); /* wait for other threads */ for (i=1; i<nthreads; i++) { pthread_join(thread_id[i], NULL); } /* add partial sums */ sum = 0.0; for (i=0; i<nthreads; i++) { sum += localsum[i]; } pi = h*sum; /* print the result */ printf("pi computes to: %20.16lf\n", pi); printf("and is: %20.16lf\n", PI25DT); } /* routine called by the threads * gets arguments myid, nthreads, n, h, localsum * returns result in localsum[myid] */ void *par_loop(void *args) { thread_arg_t * myarg_p = (thread_arg_t *) args; int myid, nthreads, n; double h; double *localsum; int i; double x; double f(double x); /* unpack arguments */ nthreads = myarg_p->nthreads; myid = myarg_p->myid; n = myarg_p->n; h = myarg_p->h; localsum = myarg_p->localsum; /* threads's share of work */ localsum[myid] = 0.0; for (i=myid; i<n; i+= nthreads) { x = h * (i - 0.5); localsum[myid] += f(x); } return(NULL); } double f(double x) { return 4.0 / (1.0 + x*x); }