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

1.23 2.0 main test-branch
Last change on this file since fffb3b88 was 841d45a, checked in by Manchun Zheng <zmanchun@…>, 11 years ago

cleaned up elaborate calls

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

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