prng_mpi.c 2.75 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
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
#include <stdio.h> // printf
#include <stdlib.h> // EXIT_SUCCESS
#include <mpi.h>

#include "prng_shared.h"

int main(int argc, char* argv[]) {
    int seed;
    int N;
    int i;
    int number_of_workers;
    int N_per_worker;
    int my_process_id;
    double *seq;
    double *my_seq;

    // 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, &my_process_id);
    MPI_Comm_size(MPI_COMM_WORLD, &number_of_workers);

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

    // get number of workers and this workers id
    MPI_Comm_rank(MPI_COMM_WORLD, &my_process_id);
    MPI_Comm_size(MPI_COMM_WORLD, &number_of_workers);

    // exit if work cannot be divided equally among workers
    if ( (N % number_of_workers) != 0 ) {
        printf("Cannot equally divide %d numbers by %d workers \n", N, number_of_workers);
        exit(EXIT_FAILURE);
    }

    // calculate numbers to be generated by each process
    N_per_worker = N / number_of_workers;

    // allocate and array to hold N_per_worker random numbers
    my_seq = malloc(N_per_worker * sizeof(double));
    // exit if allocation fails
    if (my_seq == NULL) {
        printf("Cannot allocate space for %d numbers\n", N_per_worker);
        exit(EXIT_FAILURE);
    }

    // adjust seed so that each process creates a different number sequence
    seed = seed + my_process_id;

    // generate N_per_worker random numbers and save them in the array
    // please remember that each process will have its own memory context
    for (i=0; i<N_per_worker; i++) {
        my_seq[i] = (double)rand_r(&seed) / (double)RAND_MAX;
    }

    // in the following step, sequences from all workers will be gathered on
    // the main process. in order to do that, memory space to accommodate all
    // the numbers have to be allocated
    if (my_process_id == 0) {
        seq = malloc(N * sizeof(double));
        // exit if allocation fails
        if (seq == NULL) {
            printf("Cannot allocate space for %d numbers\n", N);
            exit(EXIT_FAILURE);
        }
    }

    // everyone (including the main process) will send N_per_worker numbers from
    // their my_seq buffer to the seq buffer in the main process, using different offsets
    MPI_Gather(my_seq, N_per_worker, MPI_DOUBLE, seq, N_per_worker, MPI_DOUBLE, 0, MPI_COMM_WORLD);

    // print the generated random numbers, showing 8 digits after the decimal point
    // this step will only be executed in the main process
    if(my_process_id == 0) {
        for (i=0; i<N; i++) {
            printf("%10.8lf\n", seq[i]);
        }
    }

    // cleanly terminate MPI subsystem
    MPI_Finalize();

    return EXIT_SUCCESS;

}