| [e48510a] | 1 | /**********************************************************************
|
|---|
| 2 | * FILE: mpi_pi_send.c
|
|---|
| 3 | * DESCRIPTION:
|
|---|
| 4 | * MPI pi Calculation Example - C Version
|
|---|
| 5 | * Point-to-Point communications example
|
|---|
| 6 | * This program calculates pi using a "dartboard" algorithm. See
|
|---|
| 7 | * Fox et al.(1988) Solving Problems on Concurrent Processors, vol.1
|
|---|
| 8 | * page 207. All processes contribute to the calculation, with the
|
|---|
| 9 | * master averaging the values for pi. This version uses low level
|
|---|
| 10 | * sends and receives to collect results.
|
|---|
| 11 | * AUTHOR: Blaise Barney. Adapted from Ros Leibensperger, Cornell Theory
|
|---|
| 12 | * Center. Converted to MPI: George L. Gusciora, MHPCC (1/95)
|
|---|
| 13 | * LAST REVISED: 06/13/13 Blaise Barney
|
|---|
| 14 | **********************************************************************/
|
|---|
| 15 | #include "mpi.h"
|
|---|
| 16 | #include <stdio.h>
|
|---|
| 17 | #include <stdlib.h>
|
|---|
| 18 |
|
|---|
| 19 | double dboard (int darts);
|
|---|
| 20 | #define DARTS 5 /* number of throws at dartboard */
|
|---|
| 21 | #define ROUNDS 5 /* number of times "darts" is iterated */
|
|---|
| 22 | #define MASTER 0 /* task ID of master task */
|
|---|
| 23 |
|
|---|
| 24 | int main (int argc, char *argv[])
|
|---|
| 25 | {
|
|---|
| 26 | double
|
|---|
| 27 | homepi, /* value of pi calculated by current task */
|
|---|
| 28 | pi, /* average of pi after "darts" is thrown */
|
|---|
| 29 | avepi, /* average pi value for all iterations */
|
|---|
| 30 | pirecv, /* pi received from worker */
|
|---|
| 31 | pisum; /* sum of workers pi values */
|
|---|
| 32 | int
|
|---|
| 33 | taskid, /* task ID - also used as seed number */
|
|---|
| 34 | numtasks, /* number of tasks */
|
|---|
| 35 | source, /* source of incoming message */
|
|---|
| 36 | mtype, /* message type */
|
|---|
| 37 | rc, /* return code */
|
|---|
| 38 | i, n;
|
|---|
| 39 | MPI_Status status;
|
|---|
| 40 |
|
|---|
| 41 | /* Obtain number of tasks and task ID */
|
|---|
| 42 | MPI_Init(&argc,&argv);
|
|---|
| 43 | MPI_Comm_size(MPI_COMM_WORLD,&numtasks);
|
|---|
| 44 | MPI_Comm_rank(MPI_COMM_WORLD,&taskid);
|
|---|
| 45 | printf ("MPI task %d has started...\n", taskid);
|
|---|
| 46 |
|
|---|
| 47 | /* Set seed for random number generator equal to task ID */
|
|---|
| 48 | srandom (taskid);
|
|---|
| 49 |
|
|---|
| 50 | avepi = 0;
|
|---|
| 51 | for (i = 0; i < ROUNDS; i++) {
|
|---|
| 52 | /* All tasks calculate pi using dartboard algorithm */
|
|---|
| 53 | homepi = dboard(DARTS);
|
|---|
| 54 |
|
|---|
| 55 | /* Workers send homepi to master */
|
|---|
| 56 | /* - Message type will be set to the iteration count */
|
|---|
| 57 | if (taskid != MASTER) {
|
|---|
| 58 | mtype = i;
|
|---|
| 59 | rc = MPI_Send(&homepi, 1, MPI_DOUBLE,
|
|---|
| 60 | MASTER, mtype, MPI_COMM_WORLD);
|
|---|
| 61 | if (rc != MPI_SUCCESS)
|
|---|
| 62 | printf("%d: Send failure on round %d\n", taskid, mtype);
|
|---|
| 63 | }
|
|---|
| 64 | else
|
|---|
| 65 | {
|
|---|
| 66 | /* Master receives messages from all workers */
|
|---|
| 67 | /* - Message type will be set to the iteration count */
|
|---|
| 68 | /* - Message source will be set to the wildcard DONTCARE: */
|
|---|
| 69 | /* a message can be received from any task, as long as the */
|
|---|
| 70 | /* message types match */
|
|---|
| 71 | /* - The return code will be checked, and a message displayed */
|
|---|
| 72 | /* if a problem occurred */
|
|---|
| 73 | mtype = i;
|
|---|
| 74 | pisum = 0;
|
|---|
| 75 | for (n = 1; n < numtasks; n++) {
|
|---|
| 76 | rc = MPI_Recv(&pirecv, 1, MPI_DOUBLE, MPI_ANY_SOURCE,
|
|---|
| 77 | mtype, MPI_COMM_WORLD, &status);
|
|---|
| 78 | if (rc != MPI_SUCCESS)
|
|---|
| 79 | printf("%d: Receive failure on round %d\n", taskid, mtype);
|
|---|
| 80 | /* keep running total of pi */
|
|---|
| 81 | pisum = pisum + pirecv;
|
|---|
| 82 | }
|
|---|
| 83 | /* Master calculates the average value of pi for this iteration */
|
|---|
| 84 | pi = (pisum + homepi)/numtasks;
|
|---|
| 85 | /* Master calculates the average value of pi over all iterations */
|
|---|
| 86 | avepi = ((avepi * i) + pi)/(i + 1);
|
|---|
| 87 | printf(" After %8d throws, average value of pi = %10.8f\n",
|
|---|
| 88 | (DARTS * (i + 1)),avepi);
|
|---|
| 89 | }
|
|---|
| 90 | }
|
|---|
| 91 |
|
|---|
| 92 | if (taskid == MASTER)
|
|---|
| 93 | printf ("\nReal value of PI: 3.1415926535897 \n");
|
|---|
| 94 |
|
|---|
| 95 | MPI_Finalize();
|
|---|
| 96 | return 0;
|
|---|
| 97 | }
|
|---|
| 98 |
|
|---|
| 99 |
|
|---|
| 100 | /**************************************************************************
|
|---|
| 101 | * subroutine dboard
|
|---|
| 102 | * DESCRIPTION:
|
|---|
| 103 | * Used in pi calculation example codes.
|
|---|
| 104 | * See mpi_pi_send.c and mpi_pi_reduce.c
|
|---|
| 105 | * Throw darts at board. Done by generating random numbers
|
|---|
| 106 | * between 0 and 1 and converting them to values for x and y
|
|---|
| 107 | * coordinates and then testing to see if they "land" in
|
|---|
| 108 | * the circle." If so, score is incremented. After throwing the
|
|---|
| 109 | * specified number of darts, pi is calculated. The computed value
|
|---|
| 110 | * of pi is returned as the value of this function, dboard.
|
|---|
| 111 | *
|
|---|
| 112 | * Explanation of constants and variables used in this function:
|
|---|
| 113 | * darts = number of throws at dartboard
|
|---|
| 114 | * score = number of darts that hit circle
|
|---|
| 115 | * n = index variable
|
|---|
| 116 | * r = random number scaled between 0 and 1
|
|---|
| 117 | * x_coord = x coordinate, between -1 and 1
|
|---|
| 118 | * x_sqr = square of x coordinate
|
|---|
| 119 | * y_coord = y coordinate, between -1 and 1
|
|---|
| 120 | * y_sqr = square of y coordinate
|
|---|
| 121 | * pi = computed value of pi
|
|---|
| 122 | ****************************************************************************/
|
|---|
| 123 |
|
|---|
| 124 | double dboard(int darts)
|
|---|
| 125 | {
|
|---|
| 126 | #define sqr(x) ((x)*(x))
|
|---|
| 127 | //long random(void);
|
|---|
| 128 | double x_coord, y_coord, pi, r;
|
|---|
| 129 | int score, n;
|
|---|
| 130 | unsigned int cconst = 9; /* must be 4-bytes in size */
|
|---|
| 131 | /*************************************************************************
|
|---|
| 132 | * The cconst variable must be 4 bytes. We check this and bail if it is
|
|---|
| 133 | * not the right size
|
|---|
| 134 | ************************************************************************/
|
|---|
| 135 | /*if (sizeof(cconst) != 4) {
|
|---|
| 136 | printf("Wrong data size for cconst variable in dboard routine!\n");
|
|---|
| 137 | printf("See comments in source file. Quitting.\n");
|
|---|
| 138 | exit(1);
|
|---|
| 139 | }*/
|
|---|
| 140 | /* 2 bit shifted to MAX_RAND later used to scale random number between 0 and 1 */
|
|---|
| 141 | //cconst = 2 << (31 - 1);
|
|---|
| 142 | score = 0;
|
|---|
| 143 |
|
|---|
| 144 | /* "throw darts at board" */
|
|---|
| 145 | for (n = 1; n <= darts; n++) {
|
|---|
| 146 | /* generate random numbers for x and y coordinates */
|
|---|
| 147 | r = (double)random()/cconst;
|
|---|
| 148 | x_coord = (2.0 * r) - 1.0;
|
|---|
| 149 | r = (double)random()/cconst;
|
|---|
| 150 | y_coord = (2.0 * r) - 1.0;
|
|---|
| 151 |
|
|---|
| 152 | /* if dart lands in circle, increment score */
|
|---|
| 153 | if ((sqr(x_coord) + sqr(y_coord)) <= 1.0)
|
|---|
| 154 | score++;
|
|---|
| 155 | }
|
|---|
| 156 |
|
|---|
| 157 | /* calculate pi */
|
|---|
| 158 | pi = 4.0 * (double)score/(double)darts;
|
|---|
| 159 | return(pi);
|
|---|
| 160 | }
|
|---|
| 161 |
|
|---|
| 162 |
|
|---|