Let use have a look at the slave program. It is reprinted below for your convenience.
else { /* I am not the master */
int sum, row;
MPI_Bcast(b, COLS, MPI_INT, MASTER_RANK, MPI_COMM_WORLD);
fprintf(my_logfile, "received broadcast from %d\n", MASTER_RANK);
MPI_Recv(int_buffer, COLS, MPI_INT, MASTER_RANK, MPI_ANY_TAG,
MPI_COMM_WORLD, &status);
fprintf(my_logfile, "received a message from %d, tag %d\n",
status.MPI_SOURCE, status.MPI_TAG);
while (status.MPI_TAG != ROWS) { /* The job is not finished */
row = status.MPI_TAG; sum = 0;
for (i = 0; i < COLS; i++) sum = sum + int_buffer[i] * b[i];
int_buffer[0] = sum;
MPI_Send (int_buffer, 1, MPI_INT, MASTER_RANK, row, MPI_COMM_WORLD);
fprintf(my_logfile, "sent row %d to %d\n", row, MASTER_RANK);
MPI_Recv (int_buffer, COLS, MPI_INT, MASTER_RANK, MPI_ANY_TAG,
MPI_COMM_WORLD, &status);
fprintf(my_logfile, "received a message from %d, tag %d\n",
status.MPI_SOURCE, status.MPI_TAG);
}
fprintf(my_logfile, "exiting on tag %d\n", status.MPI_TAG);
}
The slave processes begin their career by receiving vector
b that
has been broadcast by the master. This is the slave-side of the broadcast call
matching the master's call:
MPI_Bcast(b, COLS, MPI_INT, MASTER_RANK, MPI_COMM_WORLD);
After they have received their copies of
b, they log
this event on their respective log files and wait for the first batch
of jobs to be sent to them by the master process.
MPI_Recv(int_buffer, COLS, MPI_INT, MASTER_RANK, MPI_ANY_TAG,
MPI_COMM_WORLD, &status);
They log this event on their log files too. Then they get to work.
The work is done within the large
while (status.MPI_TAG != ROWS) { /* The job is not finished */
blah... blah... blah...
}
loop. Every time a slave process receives a message from the master
process it checks if the tag of the message is less than
ROWS. Remember that having received a message with tag
ROWS implies the termination of the contract.
If the tag is kosher, the slave process does the following:
row = status.MPI_TAG; sum = 0;
for (i = 0; i < COLS; i++) sum = sum + int_buffer[i] * b[i];
int_buffer[0] = sum;
MPI_Send (int_buffer, 1, MPI_INT, MASTER_RANK, row, MPI_COMM_WORLD);
fprintf(my_logfile, "sent row %d to %d\n", row, MASTER_RANK);
The row number is extracted from the tag of the message. Then the
slave process evaluates
Finally, the slave process waits for another message from the master process, reads it, and logs it on the log file:
MPI_Recv (int_buffer, COLS, MPI_INT, MASTER_RANK, MPI_ANY_TAG,
MPI_COMM_WORLD, &status);
fprintf(my_logfile, "received a message from %d, tag %d\n",
status.MPI_SOURCE, status.MPI_TAG);
Then it's back to the top of the loop: check the tag, if the tag is OK perform the computation,
otherwise print a farewell message on the log file, close the file
and hit MPI_Finalize().