CSL-342: Parallel Programming lab
Semester BSIT – 06
Student Name: Muhammad Faisal
Registration: 43865
Lab 09: Performing Parallel Rank with MPI
Exercises
Exercise 1
Write a program to finding the standard deviation of a distributed set of
numbers. For those that may have forgotten, standard deviation is a measure
of the dispersion of numbers from their mean. A lower standard deviation
means that the numbers are closer together and vice versa for higher standard
deviations.
Code
#include <stdio.h> #include <stdlib.h> #include <stdio.h> #include <stdlib.h>
#include <mpi.h> #include <math.h> #include <mpi.h> #include <assert.h>
#include <assert.h> #include <time.h>
// Creates an array of random numbers. // Creates an array of random numbers.
Each number has a value from 0 - 1 float Each number has a value from 0 - 1 float
*create_rand_nums(int num_elements) { *create_rand_nums(int num_elements) {
float *rand_nums = (float float *rand_nums = (float
*)malloc(sizeof(float) * num_elements); *)malloc(sizeof(float) * num_elements);
assert(rand_nums != NULL); int i; for assert(rand_nums != NULL); int i; for
(i = 0; i < num_elements; i++) { (i = 0; i < num_elements; i++) {
rand_nums[i] = (rand() / rand_nums[i] = (rand() /
(float)RAND_MAX); } return rand_nums; (float)RAND_MAX); } return rand_nums;
} }
int main(int argc, char** argv) { if int main(int argc, char** argv) { if
(argc != 2) { fprintf(stderr, "Usage: (argc != 2) { fprintf(stderr, "Usage:
avg num_elements_per_proc\n"); avg num_elements_per_proc\n");
exit(1); } exit(1); }
int num_elements_per_proc = int num_elements_per_proc =
atoi(argv[1]); atoi(argv[1]);
MPI_Init(NULL, NULL); MPI_Init(NULL, NULL);
int world_rank; int world_rank;
MPI_Comm_rank(MPI_COMM_WORLD, MPI_Comm_rank(MPI_COMM_WORLD,
&world_rank); int world_size; &world_rank); int world_size;
MPI_Comm_size(MPI_COMM_WORLD, MPI_Comm_size(MPI_COMM_WORLD,
&world_size); &world_size);
// Create a random array of elements on // Create a random array of elements on
all processes. all processes.
srand(time(NULL)*world_rank); // Seed the srand(time(NULL)*world_rank); // Seed
random number generator of processes the random number generator to get
uniquely float *rand_nums = NULL; different results each time for each
rand_nums = processor float *rand_nums = NULL;
create_rand_nums(num_elements_per_proc); rand_nums =
// Sum the numbers locally float create_rand_nums(num_elements_per_proc);
local_sum = 0; int i; for (i = 0; i <
num_elements_per_proc; i++) { float local_sum = 0; int i; for (i =
local_sum += rand_nums[i]; } 0; i < num_elements_per_proc; i++) {
// Reduce all of the local sums into local_sum += rand_nums[i]; }
the global sum in order to // calculate // Print the random numbers on each
the mean float global_sum; process printf("Local sum for process
MPI_Allreduce(&local_sum, &global_sum, 1, %d - %f, avg = %f\n",
MPI_FLOAT, MPI_SUM, world_rank, local_sum, local_sum /
MPI_COMM_WORLD); float mean = num_elements_per_proc);
global_sum / (num_elements_per_proc * // Reduce all of the local sums into
world_size); the global sum float global_sum;
// Compute the local sum of the squared MPI_Reduce(&local_sum, &global_sum, 1,
differences from the mean float MPI_FLOAT, MPI_SUM, 0,
local_sq_diff = 0; for (i = 0; i < MPI_COMM_WORLD);
num_elements_per_proc; i++) { // Print the result if (world_rank ==
local_sq_diff += (rand_nums[i] - mean) * 0) { printf("Total sum = %f, avg =
(rand_nums[i] - mean); } %f\n", global_sum, global_sum
// Reduce the global sum of the squared / (world_size * num_elements_per_proc));
differences to the root process // and }
print off the answer float // Clean up free(rand_nums);
global_sq_diff; MPI_Barrier(MPI_COMM_WORLD);
MPI_Reduce(&local_sq_diff, MPI_Finalize(); }
&global_sq_diff, 1, MPI_FLOAT, MPI_SUM,
0, MPI_COMM_WORLD);
if (world_rank == 0) { float stddev =
sqrt(global_sq_diff /
(num_elements_per_proc * world_size));
printf("Mean - %f, Standard deviation =
%f\n", mean, stddev); }
// Clean up free(rand_nums);
MPI_Barrier(MPI_COMM_WORLD);
MPI_Finalize(); }
Output: