I am struggling with an assigment here.
Case:
Write a program in C++ that estimates the value of Pi using the Monte Carlo method.
Make a class that does the estimation of Pi (
EstimatePi
, as i call it). The user determines how many times the Pi value is estimated (from the command line)
The main program will create instances of
EstimatePi
as child processes. Each instance estimates the value of pi, and saves it to a file. The parent process will wait for the child to finish after which it reads the contents of the child process, and prints the results.
The program should run like this from the terminal
The results from the calculation processes must be presented in the order in which they are completed. The
program should not wait for all calculation processes before the results presented
eg.
Process 6044 terminated normally with return value 0 PI: 3.141957
Process 6049 terminated normally with return value 0 PI: 3.140922
...
Process 6048 terminated normally with return value 0 PI: 3.141382
Process 6053 terminated normally with return value 0 PI: 3.141528
Average: 3.14147
|
My problem
My own output gives me the reverse i.e last process done comes first and my average pi which is supposed to be after the main program terminates, comes after the children
Here is my sample output from
Estimating pi 5 processes with 100000 iterations for each process
Process #1 with pid: 20261 estimated pi: 3.141480
Process #2 with pid: 20297 estimated pi: 3.135920
Process #3 with pid: 20333 estimated pi: 3.134560
Process #4 with pid: 20371 estimated pi: 3.148080
Process #5 with pid: 20410 estimated pi: 3.150200
Average pi: 3.142048
Calculations took: 10.44 seconds
Process 20410 terminated normally with return value 0 PI: 3.150200
Process 20371 terminated normally with return value 0 PI: 3.148080
Process 20333 terminated normally with return value 0 PI: 3.182020
Process 20297 terminated normally with return value 0 PI: 3.135920
Process 20261 terminated normally with return value 0 PI: 3.244940
Press <RETURN> to close this window...
|
Code snippet from main
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
|
#include <vector>
#include <numeric>
#include <chrono>
#include <unistd.h>
#include <iomanip>
#include <sys/wait.h>
#include "EstimatePi.h"
#include "CommandLineHandler.h"
#include "Process.h"
#include <cstdint>
int main(int argc, char* argv[])
{
const auto start = std::chrono::steady_clock::now();
IntegerPair values{};
double piValues{};
double averagePi{};
CommandLineHandler command(argc, argv); // Process commands and extract values
if(command.isGoodParameters()){ // CommandLine values have been obtained
values = command.getValues();
int processes = values.first;
int iterations = values.second;
int wstatus;
// tell user what is happening..
std::cout << "Estimating pi " << processes << " processes with "
<< iterations << " iterations for each process\n" << std::endl;
for(int i = 1; i <= processes; i++){
pid_t cpid;
double pi{};
cpid = fork();
if(cpid == -1){
std::cerr << "Child creation unsuccessful" << std::endl;
}
if(cpid == 0){ /** Child process */
EstimatePi estimate(iterations);
pi = estimate.getPi();
// Get this process and save the pid and pi values to file
Process p(getpid(), pi);
p.saveProcessToFile();
// for debugging
std::cout << "Process #" << i << " with pid: " << getpid()
<< " estimated pi: " << std::setprecision(6)
<< std::fixed<< pi << std::endl;
piValues += pi;
averagePi = piValues/i;
}else{ /** Parent process*/
pid_t wId;
do{
wId = waitpid(cpid, &wstatus, WUNTRACED | WCONTINUED);
if(wId == -1){
std::cerr << "A problem occured " << std::endl;
}
if (WIFEXITED(wstatus)) {
Process p;
p.readProcessFromFile(cpid);
std::cout << "Process " << cpid
<< " terminated normally with return value "
<< wstatus << " PI: " << std::setprecision(6)
<< std::fixed << p.getPi() << std::endl;
// delete the file
std::remove(std::to_string(cpid).c_str());
}else if(WIFSIGNALED(wstatus)){
std::cerr << "Process " << cpid << " killed by signal"
<< WTERMSIG(wstatus) << std::endl;
}
else if(WIFSTOPPED(wstatus)){
std::cerr << "Process " << cpid << " stopped by signal"
<< WSTOPSIG(wstatus)<< std::endl;
}else if(WIFCONTINUED(wstatus)){
std::cerr << "Process " << cpid << " continuing..."
<< std::endl;
}
}while (!WIFEXITED(wstatus) && !WIFSIGNALED(wstatus));
exit(EXIT_SUCCESS);
}
}
const auto end = std::chrono::steady_clock::now();
const auto diff = end - start;
std::cout << "Average pi: " << std::setprecision(6) << std::fixed
<< averagePi << std::endl;
std::cout << "\nCalculations took: " << std::setprecision(2)
<<(std::chrono::duration<double, std::milli>(diff).count())/1000
<< " seconds" << std::endl;
}// END OF GOOD COMMANDLINE STUFF
/*Bad command line stuff should have been printed already if that is the
case since they are printed with std::cerr*/
return 0;
}
|
Thanks for your feedbacks