Exemplar pi area intro

Computing
as an area under a curve.
Problem definition
Often, we can estimate a desired quantity by finding the area under a curve (an integral). As an
example of this type of computation, we will estimate the value π. Since the area formula for a
circle is π ⋅ r 2 , we can compute π by finding the area of a unit circle, i.e., a circle with radius r=1.
€Algorithmic strategy
The formula for the unit circle is x2 + y2 = 1. Solving for y, we get the formula
.
Note that each value of x between
and
, yields two values of y according to this
formula, corresponding to the upper and lower semicircles in Figure 1.
Figure 1: A
Since the entire circle’s area is π, we will approximate the area of the blue semicircle—i.e., the
area under the curve 1 − x 2 —then multiply by 2. To approximate that area under a curve, we
will add up the areas of rectangles that approximately cover the area of that semicircle, as
illustrated in Figure 2.
€
Figure 2: Approximating area under a curve using rectangles.
This diagram shows 12 rectangles of equal width that approximately cover the blue
semicircular area. Each rectangle is positioned over a subinterval of the -axis interval [-1,1],
and the height of a rectangle is the function’s value at some value
in that rectangle’s
subinterval. Thus, the area of a rectangle is
. We must add up the areas of all
these rectangles, then double that sum to get the approximation of π.
The more rectangles we use, the greater accuracy we expect in our rectangle approximation to
the exact area under the semicircular curve
. Therefore, we will compute the sum with
millions of thin rectangles in order to get better accuracy for our estimate of .
Note: The accuracy of our estimate depends on how many rectangles we use, and to a lesser
extent on how we choose the values . We have illustrated in the diagram above choosing
as the midpoint of each subinterval, which visibly causes the sum of rectangle areas to be a
reasonable approximation to the exact semicircular area we seek. If
represents the midpoint
of the th rectangle, then
where
h = 2.0 /N
in terms of the number of rectangles N.
€
Parallel Design Patterns
As described in the module Introduction to Parallel Design Patterns, the OPL system of parallel
patterns is organized into four levels.
• The top level, called the Application Architecture Level, consists of structural and
computational patterns for designing large pieces of software (whether or not that
software will be implemented with parallelism).
•
Implementing this problem will not require a large software application – it’s more on the
scale of a particular iterative computation within an application. Therefore, we will not
need to consider a combination of structural and computational patterns to solve this
problem. We need only find a way to add up many areas of rectangles, then multiply by
2.
The next level of OPL patterns is the Parallel Algorithms Strategy Level. Two
patterns at this level relate to our discussion above.
o The Data parallel pattern involves applying the same computational operations to
multiple data values, assuming that those operations can be performed
independently for different data values. We can consider the values x i as our
multiple data values, and the rectangle-area computation as our operations.
o The Geometric decomposition pattern involves breaking a large computation up
into smaller “chunks” that we can compute in parallel. If we use a large number
€
of rectangles N in our area approximation, we can apply this pattern by having
multiple parallel computations that each add the areas of a subset of the
rectangles.
Note: These patterns (as we have just described them) indicate strategies for designing
parallel solutions to our problem which will prove useful when we write parallel code to
compute π. However, our problem may not quite fit the exact OPL definitions of these
terms. In particular, OPL refers to a data structure for both of these pattern names,
whereas we might simply add up areas of rectangles in a loop without an explicit data
structure of values. Also, the OPL Geometric decomposition pattern refers to
concurrently updatable “chunks,” whereas our “chunks” of data values will never change.
Nevertheless, these two algorithmic strategy patterns will help guide us to good
parallelizations for given computational platforms.
A sequential implementation
We will develop and discuss parallel solutions to our pi-as-area problem in other modules. For
now, we will present sequential code for a solution, as a reference point for the parallel
solutions.
As suggested above, we can use a simple programming loop to add the areas of all the
rectangles, as in the following C language code (the ellipses … indicate omitted code).
sum = 0;
width = 2.0 / numRect;
for ( i = 0; i < numRect; i++ ) {
x = -1 + ( i + 0.5 ) * width;
sum += sqrt( 1 - x * x ) * width;
}
pi = sum*2.0;
In this code segment, sum , pi , and x are floating-point variables, where x represents an xvalue that determines the height of a rectangle, and we use the more self-explanatory names
width and numRect in place of the symbols h and N in our mathematical explanation.
See the program pi_area_serial.c listed in the appendix of this module for a complete
implementation.
Further Exploration:
● Try compiling and running this program on your system. Observe that the code accepts
one command-line argument, for specifying a value for numRect .
● The default number of rectangles in pi_area_serial.c is 10 million. Time a run of the
program with that default number of rectangles, then use the program’s optional
command-line argument to compare with the timing for other rectangle counts, such as
100 million, 1 billion, 100,000, etc. Do these timings vary as you might expect?
● Here is an alternative approach to computing the value of x for each rectangle:
sum = 0;
width = 2.0 / numRect;
x = -1 + width/2;
for ( i = 0; i < numRect; i++ ) {
x += width;
sum += sqrt( 1 - x * x ) * width;
}
pi = sum*2.0;
Could there be a difference in the resulting value of pi if we use this approach rather
than the original approach for computing x ? Explain.
Appendix: Complete listing of pi_area_serial.c
/* Estimate pi as twice the area under a semicircle
Command-line arguments (optional, default values below).
1. first command line arg is integer number of rectangles to use
WARNING: minimal error checking is performed on this command-line arg */
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#define NUM_RECTANGLES 10000000;
/* default number of rectangles */
int main(int argc, char** argv) {
double width;
/* width of a rectangle subinterval */
double x;
/* an x_i value for determining height of rectangle */
double sum;
/* accumulates areas all rectangles so far */
long numRect = NUM_RECTANGLES; /* number of rectangles */
long i; /* loop control */
/* parse command-line arguments, if any */
if (argc > 1)
numRect = strtol(argv[1], NULL, 10);
if (numRect <= 0) {
printf("Error in command-line argument\n");
return 1; /* indicates error exit */
}
/* compute the estimate */
sum = 0;
width = 2.0 / numRect;
for ( i = 0; i < numRect; i++ ) {
x = -1 + ( i + 0.5 ) * width;
sum += sqrt( 1 - x * x ) * width;
}
pi = sum*2.0;
printf("With n = %d rectangles, ", numRect);
printf("the estimate of pi is %.20g\n", sum);
return 0;
}