5.1. Broadcast from conductor to workers¶
We will look at three types of data that can be created in the conductor and sent to the workers. Rather than use send and receive, we will use a special new function called bcast.
Note
In each code example, note how the conductor does one thing, and the workers do another, but all of the processes execute the bcast function.
5.1.1. Broadcast File Content¶
Navigate to: ../08.broadcast/
Make and run the code:
make
mpirun -hostfile ~/hostfile -np N ./broadcast
Here the N signifies the number of processes to start up in MPI.
Exercise:
Run, using N = from 1 through 8 processes.
5.1.1.1. Explore the code¶
Find the place in this code where the data is being broadcast to all of the processes. Match the prints to the output you observe when you run it.
You should also look at the contents of the data.txt
file in this folder.
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
int main(int argc, char** argv) {
int answer = 0;
int numProcs = 0, myRank = 0;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &numProcs);
MPI_Comm_rank(MPI_COMM_WORLD, &myRank);
if (myRank == 0) {
FILE *filePtr = fopen("data.txt", "r");
assert( filePtr != NULL );
fscanf(filePtr, " %d", &answer);
fclose(filePtr);
}
printf("BEFORE the broadcast, process %d's answer = %d\n",
myRank, answer);
MPI_Bcast(&answer, 1, MPI_INT, 0, MPI_COMM_WORLD);
printf("AFTER the broadcast, process %d's answer = %d\n",
myRank, answer);
MPI_Finalize();
return 0;
}
5.1.2. Broadcast user input¶
Navigate to: ../09.broadcastUserInput/
Make and run the code:
make
mpirun -hostfile ~/hostfile -np N ./broadcastUserInput dataString
Here the N signifies the number of processes to start up in MPI, which must be greater than one. The dataString
must be supplied and represents the string that will be broadcast from the conductor process to the workers.
For example, in this special instance, you can send a string version of an integer like this:
mpirun -hostfile ~/hostfile -np N ./broadcastUserInput “42”
Warning
This program is unlike any of the others and takes in a command line argument, as shown above.
Exercise:
Run, using N = from 1 through 8 processes, with a string of your choosing.
5.1.2.1. Explore the code¶
Find the place in this code where the data is being broadcast to all of the processes. Match the prints to the output you observe when you run it.
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#define CONDUCTOR 0
/* gets value of answer from user
* @param: argc, argument count.
* @param: argv, argument pointer array.
* @param: myRank, rank of current process
* @param: answer, variable to store value given by user
* Precondition: argc is a count of the number of arguments.
* && argv is a pointer array that points to the arguments.
* && myRank is the rank of this MPI process.
* && answer is the variable to be assigned value.
* Postcondition: answer has been filled with value from user
* if given, else answer remains set to 0.
*/
void getInput(int argc, char* argv[], int myRank, int* answer) {
if (myRank == 0){ // conductor process
if (argc == 2){
*answer = atoi(argv[1]);
}
}
MPI_Bcast(answer, 1, MPI_INT, 0, MPI_COMM_WORLD);
}
int main(int argc, char** argv) {
int answer = 0, length = 0;
int myRank = 0;
char myHostName[MPI_MAX_PROCESSOR_NAME];
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &myRank);
MPI_Get_processor_name (myHostName, &length);
printf("BEFORE the broadcast, process %d on host '%s' has answer = %d\n",
myRank, myHostName, answer);
getInput(argc, argv, myRank, &answer);
printf("AFTER the broadcast, process %d on host '%s' has answer = %d\n",
myRank, myHostName, answer);
MPI_Finalize();
return 0;
}
5.1.3. Broadcast a list¶
This just shows that other data structures can also be broadcast.
Navigate to: ../11.broadcastList/
*Make and run the code:
make
mpirun -hostfile ~/hostfile -np N ./broadcast2
Here the N signifies the number of processes to start up in MPI.
Exercise:
Run, using N = from 1 through 8 processes.
5.1.3.1. Explore the code¶
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
/* fill an array with some arbitrary values
* @param: a, an int*.
* @param: size, an int.
* Precondition: a is the address of an array of ints.
* && size is the number of ints a can hold.
* Postcondition: a has been filled with arbitrary values
* { 11, 12, 13, ... }.
*/
void fill(int* a, int size) {
int i;
for (i = 0; i < size; i++) {
a[i] = i+11;
}
}
/* display a string, a process id, and its array values
* @param: str, a char*
* @param: id, an int
* @param: a, an int*.
* Precondition: str points to either "BEFORE" or "AFTER"
* && id is the rank of this MPI process
* && a is the address of an 8-element int array.
* Postcondition: str, id, and a have all been written to stdout.
*/
void print(char* str, int id, int* a) {
printf("%s broadcast, process %d has: {%d, %d, %d, %d, %d, %d, %d, %d}\n",
str, id, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]);
}
#define MAX 8
int main(int argc, char** argv) {
int array[MAX] = {0};
int numProcs, myRank;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &numProcs);
MPI_Comm_rank(MPI_COMM_WORLD, &myRank);
if (myRank == 0) fill(array, MAX);
print("BEFORE", myRank, array);
MPI_Bcast(array, MAX, MPI_INT, 0, MPI_COMM_WORLD);
print("AFTER", myRank, array);
MPI_Finalize();
return 0;
}