- #include <stdio.h>
- #include <stdlib.h>
- #include <math.h>
- #include <mpi.h>
- #define TAG_NUMBER 100
- #define TAG_DATA 101
- #define TAG_SUM 102
- #define TAG_AVERAGE 103
- #define TAG_STD_DEV 104
- int master(int argc, char *argv[], int rank, int size);
- int slave(int rank);
- int main(int argc, char *argv[])
- {
- int rank, size;
- MPI_Init(&argc, &argv);
- MPI_Comm_rank(MPI_COMM_WORLD, &rank);
- MPI_Comm_size(MPI_COMM_WORLD, &size);
- if (size == 1)
- {
- return EXIT_FAILURE;
- }
- if (rank == 0)
- master(argc, argv, rank, size);
- else
- slave(rank);
- MPI_Finalize();
- return EXIT_SUCCESS;
- }
- int master(int argc, char *argv[], int rank, int size)
- {
- FILE *fp;
- char *file_name = "data";
- int N, N_local, N_local_residual, process, i, err;
- double *data, x, average, diff, std_dev, local_sum;
- MPI_Status recv_status;
- // parse arguments
- if (argc > 1)
- file_name = argv[1];
- // setup
- // open the file
- {
- return EXIT_FAILURE;
- }
- // read the size of the data file
- N_local = N / size; // size of data chunks on each node
- N_local_residual = N % size; // extra points for the master node
- // allocate memory to hold a data chunk
- if (data == NULL)
- {
- return EXIT_FAILURE;
- }
- for (process=1 ; process < size ; process++)
- {
- // send # of numbers to node
- MPI_Ssend(&N_local, 1, MPI_INT, process, TAG_NUMBER, MPI_COMM_WORLD);
- // read in the data
- for (i=0; i < N_local; i++)
- // send data to the node
- MPI_Ssend(data, N_local, MPI_DOUBLE, process, TAG_DATA, MPI_COMM_WORLD);
- }
- N_local += N_local_residual;
- // read in data for the master
- for (i=0; i < N_local; i++)
- // close file
- average = 0;
- for (i=0; i < N_local; i++)
- average += data[i];
- rank, N_local, average/N_local);
- // collect sums from other nodes
- for (process=1; process < size; process++)
- {
- err = MPI_Recv(&local_sum, 1, MPI_DOUBLE, MPI_ANY_SOURCE, TAG_SUM,
- MPI_COMM_WORLD, &recv_status);
- average += local_sum;
- }
- average /= N;
- // distribute average to nodes
- for (process=1; process < size; process++)
- {
- MPI_Ssend(&average, 1, MPI_DOUBLE, process, TAG_AVERAGE,
- MPI_COMM_WORLD);
- }
- // standard deviation
- std_dev = 0.0;
- for (i=0; i < N_local; i++) {
- diff = data[i] - average;
- std_dev += diff * diff;
- }
- // collect sums from other nodes
- for (process=1; process<size; process++)
- {
- MPI_Recv(&local_sum, 1, MPI_DOUBLE, MPI_ANY_SOURCE, TAG_STD_DEV,
- MPI_COMM_WORLD, &recv_status);
- std_dev = std_dev + local_sum;
- }
- // cleanup and exit
- return EXIT_SUCCESS;
- }
- int slave(int rank)
- {
- int master=0, N, i, err;
- double *data, average, sum, diff;
- MPI_Status recv_status;
- // get the number of numbers to analyze locally
- err = MPI_Recv(&N, 1, MPI_INT, master, TAG_NUMBER, MPI_COMM_WORLD,
- &recv_status);
- // allocate memory to hold a data chunk
- if (data == NULL)
- {
- return EXIT_FAILURE;
- }
- // get the data
- err = MPI_Recv(data, N, MPI_DOUBLE, master, TAG_DATA, MPI_COMM_WORLD,
- &recv_status);
- // average (local sum)
- sum = 0.0;
- for (i=0; i < N; i++)
- sum = sum + data[i];
- // send local sum to master
- MPI_Ssend(&sum, 1, MPI_DOUBLE, master, TAG_SUM, MPI_COMM_WORLD);
- // get the average
- MPI_Recv(&average, 1, MPI_DOUBLE, master, TAG_AVERAGE, MPI_COMM_WORLD,
- &recv_status);
- //standard deviation
- sum = 0.0;
- for (i=0; i < N; i++)
- {
- diff = data[i] - average;
- sum += diff * diff;
- }
- // send local sum to master
- MPI_Ssend(&sum, 1, MPI_DOUBLE, master, TAG_STD_DEV, MPI_COMM_WORLD);
- // cleanup and exit
- return EXIT_SUCCESS;
- }
Raw Paste