pi_mpi.c 1.72 KB
Newer Older
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
#include <stdio.h> // printf
#include <stdlib.h> // EXIT_SUCCESS, srand
#include <math.h> // M_PI, fabs
#include <mpi.h>

#include "pi_shared.h"

int main(int argc, char* argv[]) {
    int seed;
    int N;
    int hits;
    int hits_sum;
    double my_pi;
    int number_of_workers;
    int this_worker;
    int N_per_worker;

    // initialize MPI sybsystem
    MPI_Init(&argc,&argv);

    // get number of available processes, and a unique id for this process
    MPI_Comm_rank(MPI_COMM_WORLD, &this_worker);
    MPI_Comm_size(MPI_COMM_WORLD, &number_of_workers);

    // get parameters from command line arguments
    read_arguments(&seed, &N, argc, argv);

    // divide the workload equally among processes
    N_per_worker = N / number_of_workers;
    N = N_per_worker * number_of_workers;

    // generate N_per_worker random coordinates, get number of hits
    // (see count_hits() function for details)
    // please note that every process will start with a different seed value
    hits = count_hits(seed + this_worker, N_per_worker);

    // sum hits values from different processes
    MPI_Reduce(&hits, &hits_sum, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);

    // process the combined result (on root process only)
    if(this_worker == 0) {
        // estimate PI based on following assumptions
        //   area of circle                = PI * r^2   ~= hits
        //   area of square around circle  = (2 * r)^2  ~= N
        //   r = 1
        my_pi = 4. * ((double) hits_sum  / (double) N);

        // print seed, N, number_of_workers, result, error
        printf("%d\t%d\t%d\t%f\t%f\n", seed, N, number_of_workers, my_pi, fabs(my_pi-M_PI));

    }

    // cleanly terminate MPI subsystem
    MPI_Finalize();

    return EXIT_SUCCESS;

}