/***************************************************************/ /* matmult - parallel matrix multiplication algorithm */ /* Written by Mike Patterson for CS133, Winter 96 */ /* Adapted for Maisie v. 3.0 on 2-27-97 */ /* */ /* This program uses Cannon's algorithm to order the initial */ /* A and B matrices so that parallel calculations can occur. */ /* This algorithm first shifts the elements of row i in A, i */ /* places to the left (MOD size of the row). Column i in B */ /* is also shifted i places up (MOD size of column). After the */ /* initial data shifting, A & B are checkerboard partitioned */ /* into submatrices and parcelled out to entities running in */ /* parallel. After each iteration, data is shifted up one */ /* row for the A submatrices and left one column for the B */ /* submatrix. */ /* */ /* A and B matrices must be square for this program. The */ /* maximum dimension size allowed is 64 (or MAXDIM). For */ /* parallelization, the initial matrices are divided into */ /* sqr submatrices of dimension blocksize. Maximum allowed */ /* blocksize is 16 (defined as MAXSUBDIM). Entities are */ /* created to manage an A and a B submatrix, and return the */ /* results to the driver routine at the end of their */ /* computation. For this program, the matrices can only hold */ /* integer data. */ /* */ /* For each iteration: */ /* */ /* Each mmult entity handles multiplication of the elements */ /* in their submatrices and the message passing to their UP */ /* and LEFT neighbors (following Cannon's algorithm). They */ /* also receive data from their DOWN and RIGHT neighbors. */ /* */ /* Message traffic between the mmult entities consists of rows */ /* from the A submatrix and cols from the B submatrix, one per */ /* iteration, as the data is shifted for the calculations. */ /* */ /* Command line args: */ /* -input filename : the name of the input file */ /* -output filename : where to save resulting C matrix */ /* -block # : dimension (blocksize) of submatrices */ /* */ /* The format expected in the input file is illustrated below: */ /* although comments have been added, do not use them in file. */ /* */ /* 3 # dimension of A (and B) (3x3) */ /* 1 2 3 # first row of matrix A */ /* 4 0 2 */ /* 8 5 1 */ /* 7 1 4 # first row of matrix B */ /* 1 1 8 */ /* 0 3 3 */ /* */ /* The resulting matric C is saved to the putput file, along */ /* with dimensions of the initial matrices and the subsequent */ /* submatrix dimension used. Timing information is also */ /* printed in the output, measured starting after the data has */ /* been read in by the driver, up until just before the driver */ /* stores the answer in the file. Therefore all parallel */ /* computation (including entity creation) is timed, as well */ /* as the initial data shifting of the A and B matrices. The */ /* output file also contains the number of processes used. */ /* */ /***************************************************************/ #include #include #include #include "maisie.h" #define UP 0 #define DOWN 1 #define LEFT 2 #define RIGHT 3 #define SQR(x) ((x)*(x)) #define MAXDIM 64 #define MAXSUBDIM 16 int Mod( int numerator, int denominator) { int val = numerator % denominator; if (val < 0) val += denominator; return(val); } int FillSubMatrix( int matrix[MAXDIM][MAXDIM], int begin_i, int begin_j, int end_i, int end_j, int submatrix[MAXSUBDIM][MAXSUBDIM]) { int i, j; for (i=begin_i;i 9) { val = val / 10; size++; } return(size); } int PrintMatrix( char *filename, int matrix[MAXDIM][MAXDIM], int dim, int blocksize, float running_time) { FILE *fp; int i, j; int maxval; int padding; char formatstring[10]; if ((fp = fopen(filename, "w")) == NULL) { printf("ERROR! Unable to open output file for writing!\n"); return; } fprintf(fp, "Multiplication of %dx%d matrices, using ", dim, dim); fprintf(fp, "%dx%d submatrix size.\n", blocksize, blocksize); fprintf(fp, "Running time was %6.4f seconds ", running_time); fprintf(fp, "using %d processes\n\n", SQR(dim/blocksize)); maxval = 0; for (i=0;i MAXSUBDIM) { printf("WARNING! blocksize [%d] is larger than ", blocksize); printf("maximum allowable [%d].\n", MAXSUBDIM); printf("Resetting blocksize to %d.\n", MAXSUBDIM); blocksize = MAXSUBDIM; } if (Mod(dim,blocksize) != 0) { printf("ERROR! blocksize [%d] is not an integer ", blocksize); printf("multiple of matrix dimension [%d]\n", dim); terminate(); } subnum = dim/blocksize; /* calc submatrix dimension */ st_time = clock(); /* start timing now... */ ShiftMatrix(A, dim, LEFT); ShiftMatrix(B, dim, UP); for (i=0;i