6.1. Collective Communication: reduce function¶
The type of reduction of many values down to one can be done with different types of operators on the set of values computed by each process.
6.1.1. Reduce all values using sum and max¶
In this example, every process computes the square of (id+1). Then all those values are summed together and also the maximum function is applied.
Navigate to: ../12.reduction/
Make and run the code:
make
mpirun -hostfile ~/hostfile -np N ./reduction
Here the N signifies the number of processes to start up in mpi.
Exercises:
Run, using N = from 1 through 8 processes.
Try replacing MPI_MAX with MPI_MIN(minimum) and/or replacing MPI_SUM with MPI_PROD (product). Then save and run the code again.
6.1.1.1. Explore the code¶
Find the place in this code where the data computed on each process is being reduced to one value. Match the prints to the output you observe when you run it.
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv) {
int numProcs = -1, myRank = -1, square = -1, max = -1, sum = 0;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &numProcs);
MPI_Comm_rank(MPI_COMM_WORLD, &myRank);
square = (myRank+1) * (myRank+1);
printf("Process %d computed %d\n", myRank, square);
MPI_Reduce(&square, &sum, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
MPI_Reduce(&square, &max, 1, MPI_INT, MPI_MAX, 0, MPI_COMM_WORLD);
if (myRank == 0) {
printf("\nThe sum of the squares is %d\n\n", sum);
printf("The max of the squares is %d\n\n", max);
}
MPI_Finalize();
return 0;
}
6.1.2. Reduction on an array of values¶
We can try reduction with arrays of values.
Navigate to: ../13.reduction2/
Make and run the code:
make
mpirun -hostfile ~/hostfile -np N ./reduction2
Here the N signifies the number of processes to start up in mpi.
Exercises:
Run, using N = from 1 through 4 processes.
Uncomment the two lines of runnable code that are commented in the main() function. Observe the new results and explain why the MPI_SUM (using the + operator underneath) behaves the way it does on lists, and what the new function called sumListByElements is doing instead.
6.1.2.1. Explore the code¶
#include <mpi.h>
#include <stdio.h>
#define ARRAY_SIZE 5
void printArray(int id, char* arrayName, int* array, int SIZE);
int main(int argc, char** argv) {
int myRank = -1;
int srcArr[ARRAY_SIZE] = {0};
int destArr[ARRAY_SIZE] = {0};
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &myRank);
if (myRank == 0) {
printf("\nBefore reduction: ");
printArray(myRank, "destArr", destArr, ARRAY_SIZE);
}
for (unsigned i = 0; i < ARRAY_SIZE; i++) {
srcArr[i] = myRank * i;
}
printArray(myRank, "srcArr", srcArr, ARRAY_SIZE);
MPI_Reduce(srcArr, destArr, ARRAY_SIZE, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
if (myRank == 0) {
printf("\nAfter reduction: ");
printArray(myRank, "destArr", destArr, ARRAY_SIZE);
printf("\n");
}
MPI_Finalize();
return 0;
}
/* utility to display an array
* params: id, the rank of the current process
* arrayName, the name of the array being displayed
* array, the array being displayed
* SIZE, the number of items in array.
* postcondition:
* the id, name, and items in array have been printed to stdout.
*/
void printArray(int id, char* arrayName, int * array, int SIZE) {
printf("Process %d, %s: [", id, arrayName);
for (int i = 0; i < SIZE; i++) {
printf("%3d", array[i]);
if (i < SIZE-1) printf(",");
}
printf("]\n");
}