| 1 | #ifdef _CIVL
|
|---|
| 2 | #include <civlc.cvh>
|
|---|
| 3 | #endif
|
|---|
| 4 | /**********************************************************************
|
|---|
| 5 | ProMCore 2008
|
|---|
| 6 | February 05 - 09, 2008
|
|---|
| 7 |
|
|---|
| 8 |
|
|---|
| 9 | Example 1.2 : mpi-Pthreads-pie-collective.c
|
|---|
| 10 |
|
|---|
| 11 | Objective : Write an MPI-Pthreads program to compute the value
|
|---|
| 12 | of PI by numerical integration of a function f(x)
|
|---|
| 13 | =4/(1+x*x) between the limits 0 and 1.Pthreads and
|
|---|
| 14 | MPI Collective communication library calls are used.
|
|---|
| 15 |
|
|---|
| 16 | This example demonstrates the use of
|
|---|
| 17 |
|
|---|
| 18 | pthread_create()
|
|---|
| 19 | pthread_join()
|
|---|
| 20 | pthread_mutex_lock()
|
|---|
| 21 | pthread_mutex_unlock()
|
|---|
| 22 |
|
|---|
| 23 | MPI_Init
|
|---|
| 24 | MPI_Comm_rank
|
|---|
| 25 | MPI_Comm_size
|
|---|
| 26 | MPI_Bcast
|
|---|
| 27 | MPI_Reduce
|
|---|
| 28 | MPI_Finalize
|
|---|
| 29 |
|
|---|
| 30 | Input : Number of Intervals.
|
|---|
| 31 |
|
|---|
| 32 | Output : Calculated Value of PI.
|
|---|
| 33 |
|
|---|
| 34 | Created : January 2008
|
|---|
| 35 | National PARAM Supercomputing Facility,C-DAC,Pune.
|
|---|
| 36 |
|
|---|
| 37 |
|
|---|
| 38 | E-mail : betatest@cdac.in
|
|---|
| 39 |
|
|---|
| 40 | ************************************************************************/
|
|---|
| 41 |
|
|---|
| 42 | #include <stdio.h>
|
|---|
| 43 | #include <stdlib.h>
|
|---|
| 44 | #include <math.h>
|
|---|
| 45 | #include "mpi.h"
|
|---|
| 46 | #include <pthread.h>
|
|---|
| 47 |
|
|---|
| 48 | #ifdef _CIVL
|
|---|
| 49 | $input int NUM_INTERVAL_BOUND = 4;
|
|---|
| 50 | #endif
|
|---|
| 51 |
|
|---|
| 52 | double intervalWidth, mypi = 0.0;
|
|---|
| 53 | int *MyIntervals;
|
|---|
| 54 | int MyRank, Numprocs, Root = 0, MyCount = 0;
|
|---|
| 55 | pthread_mutex_t mypi_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|---|
| 56 |
|
|---|
| 57 | void * MyPartOfCalc(int myID)
|
|---|
| 58 | {
|
|---|
| 59 | int myInterval;
|
|---|
| 60 | double myIntervalMidPoint;
|
|---|
| 61 | double myArea = 0.0, result;
|
|---|
| 62 |
|
|---|
| 63 | myIntervalMidPoint = ((double) MyIntervals[myID] - 0.5) * intervalWidth;
|
|---|
| 64 | myArea += (4.0 / (1.0 + myIntervalMidPoint * myIntervalMidPoint));
|
|---|
| 65 |
|
|---|
| 66 | result = myArea * intervalWidth;
|
|---|
| 67 |
|
|---|
| 68 | /* Lock the mutex controlling the access to area. */
|
|---|
| 69 |
|
|---|
| 70 | pthread_mutex_lock(&mypi_mutex);
|
|---|
| 71 | mypi += result;
|
|---|
| 72 | pthread_mutex_unlock(&mypi_mutex);
|
|---|
| 73 | }
|
|---|
| 74 |
|
|---|
| 75 | double func(double x)
|
|---|
| 76 | {
|
|---|
| 77 | return (4.0 / (1.0 + x * x));
|
|---|
| 78 | }
|
|---|
| 79 |
|
|---|
| 80 | int main(int argc, char *argv[])
|
|---|
| 81 | {
|
|---|
| 82 | int NoInterval, interval, i;
|
|---|
| 83 | double pi, sum, h, x;
|
|---|
| 84 | double PI25DT = 3.141592653589793238462643;
|
|---|
| 85 | pthread_t *threads;
|
|---|
| 86 |
|
|---|
| 87 | /* ....MPI initialisation.... */
|
|---|
| 88 | MPI_Init(&argc, &argv);
|
|---|
| 89 | MPI_Comm_size(MPI_COMM_WORLD, &Numprocs);
|
|---|
| 90 | MPI_Comm_rank(MPI_COMM_WORLD, &MyRank);
|
|---|
| 91 |
|
|---|
| 92 | if (MyRank == Root) {
|
|---|
| 93 | printf("\nEnter the number of intervals : ");
|
|---|
| 94 | scanf("%d", &NoInterval);
|
|---|
| 95 | #ifdef _CIVL
|
|---|
| 96 | $assume(NoInterval <= NUM_INTERVAL_BOUND);
|
|---|
| 97 | #endif
|
|---|
| 98 | }
|
|---|
| 99 |
|
|---|
| 100 | /* ....Broadcast the number of subintervals to each processor.... */
|
|---|
| 101 | MPI_Bcast(&NoInterval, 1, MPI_INT, 0, MPI_COMM_WORLD);
|
|---|
| 102 | #ifdef _CIVL
|
|---|
| 103 | $assume(NoInterval > 0);
|
|---|
| 104 | #endif
|
|---|
| 105 | if (NoInterval <= 0) {
|
|---|
| 106 | if (MyRank == Root)
|
|---|
| 107 | printf("Invalid Value for Number of Intervals .....\n");
|
|---|
| 108 | MPI_Finalize();
|
|---|
| 109 | exit(-1);
|
|---|
| 110 | }
|
|---|
| 111 | h = 1.0 / (double) NoInterval;
|
|---|
| 112 | intervalWidth = h;
|
|---|
| 113 |
|
|---|
| 114 | /* Start Calcualtions to determine the number of intervals for each */
|
|---|
| 115 | /* processes of the Communicator. */
|
|---|
| 116 |
|
|---|
| 117 | MyCount = 0;
|
|---|
| 118 | for (interval = MyRank + 1; interval <= NoInterval; interval += Numprocs)
|
|---|
| 119 | MyCount++;
|
|---|
| 120 |
|
|---|
| 121 | MyIntervals = (int *) malloc(sizeof(int) * MyCount);
|
|---|
| 122 |
|
|---|
| 123 | for (i = 0, interval = MyRank + 1; interval <= NoInterval; i++, interval += Numprocs)
|
|---|
| 124 | MyIntervals[i] = interval;
|
|---|
| 125 |
|
|---|
| 126 | /* Start creating threads. */
|
|---|
| 127 |
|
|---|
| 128 | threads = (pthread_t *) malloc(sizeof(pthread_t) * MyCount);
|
|---|
| 129 |
|
|---|
| 130 | for (interval = 0; interval < MyCount; interval++)
|
|---|
| 131 | pthread_create(&threads[interval], NULL, (void *(*) (void *)) MyPartOfCalc, (void *) interval);
|
|---|
| 132 |
|
|---|
| 133 | for (interval = 0; interval < MyCount; interval++)
|
|---|
| 134 | pthread_join(threads[interval], NULL);
|
|---|
| 135 |
|
|---|
| 136 | /* ....Collect the areas calculated in P0.... */
|
|---|
| 137 | MPI_Reduce(&mypi, &pi, 1, MPI_DOUBLE, MPI_SUM, Root, MPI_COMM_WORLD);
|
|---|
| 138 |
|
|---|
| 139 | if (MyRank == Root) {
|
|---|
| 140 | printf("pi is approximately %.16f, Error is %.16f\n",
|
|---|
| 141 | pi, fabs(pi - PI25DT));
|
|---|
| 142 | }
|
|---|
| 143 | free(threads);
|
|---|
| 144 | free(MyIntervals);
|
|---|
| 145 | MPI_Finalize();
|
|---|
| 146 |
|
|---|
| 147 | }
|
|---|