/******************************************************** % % Written by: % -- % John L. Weatherwax 2005-05-25 % % email: wax@alum.mit.edu % % Please send comments and especially bug reports to the % above email address. % %----- A parallel program to take the transpose of the matrix "M" using threads. The transpose is stored in the matrix "T" both of global scope. */ #include #include #include int **M,**T; /* The thread argument package: */ typedef struct { int thread_number,col1,col2,size; } tpackage_t; /* Thread worker routine: */ void *transpose_worker( void *arg ){ int row, col; tpackage_t *p = (tpackage_t *) arg; if( pthread_detach( pthread_self() ) != 0 ){ fprintf(stderr,"pthread_detach != 0"); exit(2); } for( col=p->col1; col < p->col2; col++ ){ for( row=0; row < p->size; row++ ){ T[col][row] = M[row][col]; } } free(p); } /* * Main: allocates matrix, assigns values, computes the results */ extern int main(int argc, char* argv[]) { int size, row, column, P, num_cols, col1, col2; int i,j, ti; tpackage_t *p; /* An array of threads: */ pthread_t *threads; /* Check input arguments */ if( argc < 3 | argc > 3 ){ fprintf(stderr,"Expecting two input arguments:\n"); fprintf(stderr,": *n* (size of matrices)\n"); fprintf(stderr,": *P* (number of threads)\n"); exit(1); } /* Extract out the requested matrix size */ size = atoi(argv[1]); if( size <= 0 ){ fprintf(stderr,"Input argument *n* must be positive\n"); exit(1); } P = atoi(argv[2]); if( size <= 0 ){ fprintf(stderr,"Input argument *P* must be positive\n"); exit(1); } /* Create global space for the matrices and fill: */ /* M: */ M = (int**) malloc( size * sizeof(int*) ); if( !M ){ fprintf(stderr,"Memory couldn't be created\n"); exit(1); } for( row=0; row < size; row++ ){ M[row] = malloc( size*sizeof(int) ); if( !M[row] ){ fprintf(stderr,"Memory couldn't be created\n"); exit(1); } } /* T: */ T = (int**) malloc( size * sizeof(int*) ); if( !T ){ fprintf(stderr,"Memory couldn't be created\n"); exit(1); } for( row=0; row < size; row++ ){ T[row] = malloc( size*sizeof(int) ); if( !T[row] ){ fprintf(stderr,"Memory couldn't be created\n"); exit(1); } } /* Fill in matrix values, currently values are hardwired */ int counter=0; for (row = 0; row < size; row++) { for (column = 0; column < size; column++) { M[row][column] = counter++; } } /* Print matrices before: */ printf("MATRIX: The M array is;\n"); for(row = 0; row < size; row ++) { for (column = 0; column < size; column++) { printf("%5d ",M[row][column]); } printf("\n"); } /* Create "P" threads to begin transposing: each thread will transpose a selected number of COLUMNS */ threads = (pthread_t *) malloc( P*sizeof(pthread_t) ); if( !threads ){ fprintf(stderr,"Memory couldn't be created\n"); exit(1); } num_cols = (int) (size/P); for( ti=0; ti < P; ti++ ){ col1 = 0 + num_cols*ti; if( ti < P-1 ){ col2 = col1 + num_cols; }else{ col2 = size; } printf( "Thread %3d will work on rows [%6d,%6d), doing a total of %6d rows\n", ti, col1, col2, col2-col1 ); /* Create a thread package: */ p = (tpackage_t *) malloc( sizeof( tpackage_t ) ); if( !p ){ fprintf(stderr,"Memory couldn't be created\n"); exit(1); } p->thread_number = ti; p->col1 = col1; p->col2 = col2; p->size = size; /* Create a thread: */ if( pthread_create( &threads[ti], NULL, transpose_worker, (void *) p )!=0 ){ perror("pthread_create\n"); exit(1); } } /* Print results */ printf("MATRIX: The resulting matrix T is;\n"); for(row = 0; row < size; row ++) { for (column = 0; column < size; column++) { printf("%5d ",T[row][column]); } printf("\n"); } return 0; }