Write a parallel program pie.c in C or C++ (pie.cc) for Linux that computes an approximation of the number π using a series’ with N+1 terms. The series sum is partitioned in T non-overlapping partial sums, each computed by T separate child processes created with the fork() library function. This program demonstrates data parallelism and interprocess communication using pipes. Each child process could perform a (potentially) long computation on a separate CPU (or core), thus, the entire computation could reach a speedup close to T. Numbers N and T are passed from the shell to the pie program as command line parameters. The main(argc, argv[]) function call gets these parameters (T, N) in argv[1] and argv[2] as strings, respectively. (Element argv[0] contains the program name and we don’t need it.)
The first parameter, N, is the upper limit for i in the formula above. The second parameter, T, is the
number of child processes that compute partial sums. N should always be greater than T, N>T.
Otherwise the program should display an error message and call exit(1).
Use the Nilakantha approximation formula for π (http://en.wikipedia.org/wiki/Pi):
π = 3 + 4/(2*3*4) – 4/(4*5*6) + 4/(6*7*8) – 4/(8*9*10) + …. + k*4/((2*i)* (2*i+1)*( 2*i+2))+…
where k = 1 if i is odd and k = -1 if i is even and i goes from 1 to N.
The program can be run like this from the shell:
./pie N T
For instance,
./pie 100 4
This command computes the approximation with 101 terms (starting with term 3) with 4 child
processes.
Here is a description of the algorithm to be implemented.
The parent process iterates with an index variable of type int called j from 0 to T (0≤j<T). During
iteration with index j, the parent process …
1. creates a pipe associated with child process with index j
2. creates a child process with fork()
3. writes the values N, T, and j to the pipe
After ending the loop (above) that created the T child processes, the parent process starts a new loop,
with index j from 0 to T (0≤j<T). In iteration with index j, the parent process reads from the pipe
associated with child j the value of the partial sum computed by the child and adds it to an accumulator
double variable.
After the second loop ends, the parent process:
1. displays the sum approximating the value of π stored in the accumulator, with a message that
reads like:
2. The approximation of pi with N=%d and T=%d processes is %f.
(this is a C printf format string, make sure the code displays the actual numbers!)
3. waits for all child processes to end
4. exits with code 0.
The child process with index j runs its code in a function called computePartialSum.
In this function the child process does this:
1. closes any unnecessary file descriptors (which ones?)
2. reads values N,T, and j from the pipe, which were written by the parent process
3. computes the partial sum (as described below)
4. writes the partial sum to the pipe
5. calls exit(0).
NOTE: for this homework the child process should NOT rely on global variables to access N, T, and j.
These values must be read from the parent process using a pipe. Doing otherwise is considered a
mistake and points will be cut.
For example, if the user runs command
./pie 100 4
then :
child process #0 computes the partial sum for i going from 0 to 24
child process #1 computes the partial sum for i going from 25 to 49
child process #2 computes the partial sum for i going from 50 to 74
child process #3 computes the partial sum for i going from 75 to 99
Expert Answer
#include <iostream> using namespace std; int main() { int counter = 1; double odd = 1; double sum = 0; int max = 10000; bool bSign = true; double pi = 0; //4-(4/3)+(4/5)-(4/7)+(4/9)-(4/11)+... do { if(bSign) { pi += 4 / odd; bSign = false; } else { pi -= 4 / odd; bSign = true; } odd+=2; counter++; sum += pi; cout << pi << endl; } while ( counter < max ); cout << "PI : " << (sum / counter) << endl; return 0; }