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