source: CIVL/examples/mpi/mpi_pi.c@ e0fc189

1.23 2.0 main test-branch
Last change on this file since e0fc189 was e3151da, checked in by Ziqing Luo <ziqing@…>, 11 years ago

re-organized example directory

git-svn-id: svn://vsl.cis.udel.edu/civl/trunk@1763 fb995dde-84ed-4084-dfe6-e5aef3e2452c

  • Property mode set to 100644
File size: 6.0 KB
Line 
1/* FILENAME: mpi_pi.c */
2/* Calculating value of pi using a "dartboard" algorithm. In CIVL
3 * mode, the program will first let process of rank 0 do a sequential
4 * run and the results of it will be used to compare with the result
5 * of each round during parallel run.
6 * To execute: mpicc mpi_pi.c && mpiexec -n 4 ./a.out
7 * Here '4' can be replaced by any number.
8 * To verify: civl verify mpi_pi.c
9 *
10 * Modified from the original program: mpi_pi_send.c
11 * Source: https://computing.llnl.gov/tutorials/mpi/samples/C/mpi_pi_send.c */
12#include <mpi.h>
13#include <stdio.h>
14#include <stdlib.h>
15#include <assert.h>
16
17#define MASTER 0
18#define SQR(X) ((X)*(X))
19
20#ifdef _CIVL
21const int DARTSB = 2; // upper bound of DARTS
22$input int DARTS; // number of darts will be throwed
23$assume 0 < DARTS && DARTS <= DARTSB;
24const int ROUNDSB = 2; // upper bound of ROUNDS
25$input int ROUNDS; // number of rounds of throwing darts
26$assume 0 < ROUNDS && ROUNDS <= ROUNDSB;
27$input int _NPROCS = 2;
28$input int N; // length of random data array
29$input double RANDOM[N]; // random data array
30double oracle[ROUNDS]; // array of results of sequential run
31
32/* CIVL mode rand() function: returns unconstrained value as a random
33 number for a specific process throwing a specific dart right at the
34 given round. So that the sequential version and parallel version
35 are guaranteed to compute with a same set of ordered random
36 data. */
37double civlrand(int dart, int taskid, int curr_round) {
38 return RANDOM[taskid * (ROUNDS * DARTS) + dart * ROUNDS + curr_round];
39}
40#else
41int DARTS, ROUNDS;
42#endif
43int curr_round; // current round
44int taskid; // the identity of a task which is
45 // a process in parallel run.
46int tasks; // the number of tasks whichis the number
47 // of processes in parallel run
48
49/***********************************************************************
50 * Throw darts at board. Done by generating random numbers
51 * between 0 and 1 and converting them to values for x and y
52 * coordinates and then testing to see if they "land" in
53 * the circle." If so, score is incremented. After throwing the
54 * specified number of darts, pi is calculated. The computed value
55 * of pi is returned as the value of this function, dboard.
56 ************************************************************************/
57double dboard(int darts, int taskid) {
58 double x_coord, // x coordinates, between -1 and 1
59 y_coord, // y coordinates, between -1 and 1
60 pi, // pi
61 rx, // random number for x coordinate
62 ry; // random number for y coordinate
63 int score, // number of darts hit the circle
64 n;
65
66 score = 0;
67 for (n = 0; n < darts; n++) {
68 /* generate random numbers for x and y coordinates */
69#ifdef _CIVL
70 rx = civlrand(n, taskid, curr_round) / (double)RAND_MAX;
71 ry = civlrand(n, taskid, curr_round+DARTSB * _NPROCS * ROUNDSB) \
72 / (double)RAND_MAX;
73#else
74 rx = (double)rand()/(double)RAND_MAX;
75 ry = (double)rand()/(double)RAND_MAX;
76#endif
77 x_coord = (2.0 * rx) - 1.0;
78 y_coord = (2.0 * ry) - 1.0;
79
80 /* if dart lands in circle, increment score */
81 if ((SQR(x_coord) + SQR(y_coord)) <= 1.0)
82 score++;
83 }
84 /* calculate pi */
85 pi = 4.0 * (double)score/(double)darts;
86 return(pi);
87}
88
89/* In CIVL mode, process of rank 0 will do a sequential and store the
90 results in "oracle". MPI program will initialize global
91 variables */
92void initialization() {
93#ifdef _CIVL
94 double pi = 0.0;
95 double avepi = 0.0;
96
97 elaborate(DARTS);
98 elaborate(ROUNDS);
99 $assume N == DARTSB * _NPROCS * ROUNDSB * 2;
100 if(taskid == 0) {
101 for(curr_round=0; curr_round < ROUNDS; curr_round++) {
102 for(int j=0; j < tasks; j++)
103 pi += dboard(DARTS, j);
104 pi = pi / tasks;
105 avepi = ((avepi * curr_round) + pi)/(curr_round + 1);
106 oracle[curr_round] = avepi;
107 pi = 0.0;
108 }
109 }
110#else
111 DARTS = 100;
112 ROUNDS = 500;
113#endif
114}
115
116int main(int argc, char * argv[]) {
117 double homepi; // local calculated pi
118 double avepi = 0; // average value of pi of all tasks
119 //and executed rounds
120 /* Each value of a round will be used as a message tag to
121 communicate among processes at that round */
122 int mtype;
123 int rc; // returned signal of MPI routines
124
125 MPI_Init(&argc, &argv);
126 MPI_Comm_size(MPI_COMM_WORLD, &tasks);
127 MPI_Comm_rank(MPI_COMM_WORLD, &taskid);
128 initialization();
129 for(curr_round=0; curr_round<ROUNDS;curr_round++) {
130 homepi = dboard(DARTS, taskid);
131 if(taskid != MASTER){
132 mtype = curr_round;
133 rc = MPI_Send(&homepi, 1, MPI_DOUBLE,
134 MASTER, mtype, MPI_COMM_WORLD);
135 if (rc != MPI_SUCCESS)
136 printf("%d: Send failure on round %d\n", taskid, mtype);
137 } else {
138 double pi; // value of pi in a single round
139 double pisum; // sum of the values of pi calculated by all tasks
140 double pirecv; // MPI receive buffer
141
142 mtype = curr_round;
143 pisum = 0;
144 for (int n = 1; n < tasks; n++) {
145 rc = MPI_Recv(&pirecv, 1, MPI_DOUBLE, MPI_ANY_SOURCE,
146 mtype, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
147 if (rc != MPI_SUCCESS)
148 printf("%d: Receive failure on round %d\n", taskid, mtype);
149 /* keep running total of pi */
150 pisum = pisum + pirecv;
151 }
152 /* Master calculates the average value of pi for this iteration */
153 pi = (pisum + homepi)/tasks;
154 /* Master calculates the average value of pi over all iterations */
155 avepi = ((avepi * curr_round) + pi)/(curr_round + 1);
156 printf(" After %8d throws, average value of pi = %10.8f\n",
157 (DARTS * (curr_round + 1)),avepi);
158#ifdef _CIVL
159 $assert(avepi == oracle[curr_round]) : "avepi is %f but oracle[%d]"
160 " is %f\n", avepi, curr_round, oracle[curr_round];
161#endif
162 }
163 }
164 if (taskid == MASTER)
165 printf ("\nReal value of PI: 3.1415926535897 \n");
166 MPI_Finalize();
167 return 0;
168}
Note: See TracBrowser for help on using the repository browser.