gvsu/cs677/hw4/src/transpose.cc
josh 379c744d3a updated
git-svn-id: svn://anubis/gvsu@254 45c1a28c-8058-47b2-ae61-ca45b979098e
2008-11-23 16:05:51 +00:00

155 lines
4.2 KiB
C++

#include <iostream>
#include <sys/time.h>
#include <mpi.h>
using namespace std;
/*
* taskAllocate() will divide a set of total_tasks tasks into
* total_workers groups, as evenly as possible
* Parameters:
* total_tasks : IN : the total number of tasks to divide up
* total_workers : IN : the total number of workers to allocate tasks to (>0)
* this_id : IN : the id (0-based) of the task calling us for work
* first_task_id : OUT : the id (0-based) of the first task for this worker
* num : OUT : the number of tasks assigned to this worker
*/
void taskAllocate(int total_tasks, int total_workers, int this_id,
int * first_task_id, int * num)
{
int l_num;
int leftovers = total_tasks % total_workers; /* num of "leftover" tasks */
if (this_id < leftovers)
{
l_num = total_tasks / total_workers + 1; /* do one of the leftovers */
*first_task_id = l_num * this_id;
}
else
{
l_num = total_tasks / total_workers;
*first_task_id = l_num * this_id + leftovers;
}
*num = l_num;
}
void printMatrix(int * matrix, int width, int height)
{
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
cout << *matrix++ << " ";
}
cout << endl;
}
}
int main(int argc, char * argv[])
{
int my_rank;
int p; /* the number of processes */
int n = 10; /* the size of the matrix */
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
MPI_Comm_size(MPI_COMM_WORLD, &p);
#if 0
for (int i = 0; i < argc; i++)
{
if (!strncmp(argv[i], "-s", 2))
{
n = atoi(strlen(argv[i]) > 2
? argv[i] + 2
: argv[++i]);
}
}
#endif
/* Initialize the matrices */
int matrix[n][n];
int recvmatrix[n][n];
for (int i = 0; i < n; i++) /* zero the matrices for prettier */
{
for (int j = 0; j < n; j++) /* printing */
{
matrix[i][j] = 0;
recvmatrix[i][j] = 0;
}
}
/* Determine which rows I am responsible for and initialize them */
int my_first_row;
int my_num_rows;
taskAllocate(n, p, my_rank, &my_first_row, &my_num_rows);
for (int row = my_first_row; row < my_first_row + my_num_rows; row++)
{
for (int j = 0; j < n; j++)
{
matrix[row][j] = 100 * (row + 1) + (j + 1);
}
}
/* Print the initial matrices */
if (my_rank == 0)
cout << " *** Initial Matrices ***" << endl;
for (int i = 0; i < p; i++)
{
if (my_rank == i)
{
cout << "Process " << i << " matrix:" << endl;
printMatrix(&matrix[0][0], n, n);
cout << endl;
}
MPI_Barrier(MPI_COMM_WORLD); /* for printint coherently */
}
/* Populate the displacements array */
int displs[p];
int counts[p];
for (int i = 0, total = 0; i < p; i++)
{
int first;
int count;
taskAllocate(n, p, i, &first, &count);
displs[i] = total;
counts[i] = count;
total += count;
}
/* Transpose the matrix with n gather operations */
for (int i = 0, toproc = 0, proccount = counts[0]; i < n; i++)
{
int my_col_i_vals[my_num_rows];
for (int row_offset = 0; row_offset < my_num_rows; row_offset++)
my_col_i_vals[row_offset] = matrix[my_first_row + row_offset][i];
MPI_Gatherv(&my_col_i_vals[0], my_num_rows, MPI_INT,
&recvmatrix[i][0], &counts[0], &displs[0],
MPI_INT, toproc, MPI_COMM_WORLD);
proccount--;
if (proccount <= 0)
{
toproc++;
proccount = counts[toproc];
}
}
/* Print the transposed matrices */
if (my_rank == 0)
cout << " *** Final Transposed Matrices ***" << endl;
for (int i = 0; i < p; i++)
{
if (my_rank == i)
{
cout << "Process " << i << " matrix:" << endl;
printMatrix(&matrix[0][0], n, n);
cout << endl;
}
MPI_Barrier(MPI_COMM_WORLD); /* for printint coherently */
}
MPI_Finalize();
return 0;
}