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