Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <pthread.h>
- #include <string.h>
- /*
- This program aims to test the effect of using POSIX threads by testing the performance of using a pthread for each element in the resultant matrix
- and by using a pthread for every row. Performance of each case is recorded and compared against the other.
- Made by: Marwan Mokhles Abdallah ID #4926
- */
- #define LINE_MAX 512 // CONSTANT DEFINES HOW MANY CHARACTERS
- #define MAX_LENGTH 2000 // MAX LENGTH OF THE ARRAY
- int matA[MAX_LENGTH][MAX_LENGTH]; // INPUT MATRIX 1
- int matB[MAX_LENGTH][MAX_LENGTH]; // INPUT MATRIX 2
- int matRes[MAX_LENGTH][MAX_LENGTH]; // OUTPUT MATRIX
- int r1,c1,r2,c2; // ROW1,COL1,ROW2,COL2
- char* getCurrentTime(); // UTILITY FUNCTION: RETURNS CURRENT TIME IN STRING FORMAT
- void parse2mat(); // CORE FUNCTION: READS AND PARSES INPUT TO MATRIX 1 AND MATRIX 2
- void printMat(int matid); // UTILITY FUNCTION: PRINTS A MATRIX IN THE OUTPUT STREAM
- int checkValidation(); // UTILITY FUNCTION: CHECKS IF MATRIX 1 AND MATRIX 2 ARE MULTIPLICABLE
- void mulElemPerThread(); // CORE FUNCTION: CREATES A THREAD PER OUPTUT MATRIX ELEMENT, AND CALLS A FUNCTION TO CALCULATE ITS VALUE
- void* mulElem(void* arg); // CORE FUNCTION: CALCULATES THE VALUE OF AN ELEMENT IN THE OUTPUT MATRIX
- void* mulRow(void* arg); // CORE FUNCTION: CALCULATES THE VALUES OF ELEMENTS IN A SINGLE ROW OF THE OUTPUT MATRIX
- void mulRowPerThread(); // CORE FUNCTION: CREATES A THREAD PER OUTPUT MATRIX ROW, AND CALLS A FUNCTION TO CALCULATE ITS VALUES
- void eraseArrayData(); // UTILITY FUNCTION: ERASES THE OUTPUT MATRIX DATA ONCE THE RESULTS FOR TEST 1 HAS BEEN PRINTED IN THE OUTPUT FILE
- void produceOutput(float time, int matid); // CORE FUNCTION: PRINT THE OUTPUT OF TESTS 1 AND 2 IN THE OUTPUT FILE "OUTPUT.TXT"
- int main()
- {
- int i=0;
- clock_t tstart, tend,tstart2,tend2; // CLOCK VALUES USED TO CALCULATE TIME
- FILE *f = fopen("output.txt","w");
- if(f)
- {
- int status = remove("output.txt"); // IF THE FILE IS ALREADY PRESENT, DELETE IT.
- }
- printf("%s\n",getCurrentTime()); // PRINT THE CURRENT TIME
- parse2mat();
- int valid = checkValidation(); // CHECK IF MATRIX 1 AND MATRIX 2 ARE VALID FOR MULTIPLICATION
- if(valid<0)
- {
- printf("ERROR: Cannot multiply matA[%d][%d] with matB[%d][%d]. Please enter valid inputs for dimensions!",r1,c1,r2,c2);
- exit(-1);
- }
- tstart2 = clock(); // START CALCULATING TIME FOR TEST 1
- pthread_t thread[r1]; // CREATE AN ARRAY OF THREADS OF SIZE R1
- mulRowPerThread(); // PERFORM MATRIX MULTIPLICATION WHERE EVERY ELEMENT IS CALCULATED ON ITS OWN IN A SEPARATE THREAD // PERFORM MATRIX MULTIPLICATION WHERE EVERY ROW IS CALCULATED ON ITS OWN IN A SEPARATE THREAD
- tend2 = clock(); // STOP CALCULATING TIME FOR TEST 2
- produceOutput((tend2 - tstart2)/(double)CLOCKS_PER_SEC,2); // PRINT RESULTS FOR TEST 2 IN THE OUTPUT FILE
- printf("\nThe Output Matrix of dimensions [%d][%d] using a thread for each row:\n",r1,c2);
- printMat(3);
- printf("\nTime Taken: %f s\n", (tend2 - tstart2)/(double)CLOCKS_PER_SEC);
- eraseArrayData(); // ERASE OUTPUT MATRIX DATA TO MAKE SPACE FOR TEST 2
- tstart = clock();
- pthread_t thread1[r1*c2]; // START CALCULATING TIME FOR TEST 1
- mulElemPerThread(); // PERFORM MATRIX MULTIPLICATION WHERE EVERY ELEMENT IS CALCULATED ON ITS OWN IN A SEPARATE THREAD
- tend = clock(); // STOP CALCULATING TIME FOR TEST 1
- produceOutput((tend - tstart)/(double)CLOCKS_PER_SEC,1); // PRINT RESULTS FOR TEST 1 IN THE OUTPUT FILE
- printf("\nThe Output Matrix of dimensions [%d][%d] using a thread for each element:\n",r1,c2);
- printMat(3);
- printf("\nTime Taken: %f s\n", (tend - tstart)/(double)CLOCKS_PER_SEC);
- }
- // CORE FUNCTION: PRINT THE OUTPUT OF TESTS 1 AND 2 IN THE OUTPUT FILE "OUTPUT.TXT"
- void produceOutput(float time, int matid)
- {
- FILE *f;
- int i,j;
- f = fopen ("output.txt","a");
- for(i = 0; i < r1; i++)
- {
- for(j = 0; j < c2; j++)
- {
- fprintf(f,"%d\t",matRes[i][j]);
- }
- fprintf(f,"\n");
- }
- fprintf(f,"END%d\t%f\n",matid,time);
- fclose(f);
- }
- // UTILITY FUNCTION: ERASES THE OUTPUT MATRIX DATA ONCE THE RESULTS FOR TEST 1 HAS BEEN PRINTED IN THE OUTPUT FILE
- void eraseArrayData()
- {
- int i,j;
- for(i = 0; i < MAX_LENGTH; i++)
- {
- for(j = 0; j < MAX_LENGTH; j++)
- {
- matRes[i][j] = 0;
- }
- }
- }
- // CORE FUNCTION: CALCULATES THE VALUE OF AN ELEMENT IN THE OUTPUT MATRIX
- void* mulElem(void* arg)
- {
- int* pos = (int*)arg; // CAST THE ARG TO INT* TO RETRIEVE POSITION VALUES
- int i=0;
- int r = pos[0];
- int c = pos[1];
- printf("\nreceived: %d %d ",r,c);
- for(i = 0; i < c1; i++) // FOR EVERY ELEMENT
- {
- matRes[r][c] += matA[r][i] * matB[i][c]; // CALCULATE VALUE FOR EACH ELEMENT
- }
- return NULL;
- }
- // CORE FUNCTION: CREATES A THREAD PER OUPTUT MATRIX ELEMENT, AND CALLS A FUNCTION TO CALCULATE ITS VALUE
- void mulElemPerThread(){
- int i=0,j=0,k=0,m;
- int pos[2];
- pthread_t thread[r1*c2]; // CREATE AN ARRAY OF THREADS OF SIZE R1*C2
- for(i = 0; i < r1; i++)
- {
- for(j = 0; j < c2; j++)
- {
- pos[0]=i;
- pos[1]=j;
- int ret=pthread_create(&thread[k], NULL, mulElem, pos); // CREATE A THREAD WHOSE FUNCTION IS FUNCTION MULELEM
- if(ret)
- {
- printf("ERROR: Thread not created!");
- exit(-1);
- }
- k++;
- }
- }
- for( m = 0; m < r1*c2 ;m++)
- {
- pthread_join(thread[m],NULL);
- }
- }
- // CORE FUNCTION: CALCULATES THE VALUES OF ELEMENTS IN A SINGLE ROW OF THE OUTPUT MATRIX
- void* mulRow(void* args)
- {
- int row = (int)args;
- int i=0,j=0;
- for(i = 0; i < c2; i++) // FOR EVERY COLUMN
- {
- for(j = 0; j < c1; j++)
- matRes[row][i] += matA[row][j] * matB[j][i]; // CALCULATE VALUE OF ELEMENT
- }
- return NULL;
- }
- // CORE FUNCTION: CREATES A THREAD PER OUTPUT MATRIX ROW, AND CALLS A FUNCTION TO CALCULATE ITS VALUES
- void mulRowPerThread()
- {
- int i=0,k=0;
- int pos;
- pthread_t thread[r1];
- for(i = 0; i < r1; i++)
- {
- pos = i;
- int ret=pthread_create(&thread[k++], NULL, mulRow, pos); // CREATE A THREAD WHOSE FUNCTION IS FUNCTION MULROW
- if(ret)
- {
- printf("ERROR: Thread not created!");
- exit(-1);
- }
- }
- for(i=0 ; i < r1 ; i++)
- {
- pthread_join(thread[i],NULL);
- }
- }
- // UTILITY FUNCTION: RETURNS CURRENT TIME IN STRING FORMAT
- char* getCurrentTime()
- {
- time_t rawtime;
- struct tm * timeinfo;
- time ( &rawtime );
- timeinfo = localtime (&rawtime);
- return asctime (timeinfo);
- }
- // UTILITY FUNCTION: PRINTS A MATRIX IN THE OUTPUT STREAM
- void printMat(int matid)
- {
- int i=0,j=0;
- printf("\n");
- switch(matid)
- {
- case 1:
- for(i = 0; i < r1; i++)
- {
- for(j = 0; j < c1; j++)
- {
- printf("%d\t",matA[i][j]);
- }
- printf("\n");
- }
- break;
- case 2:
- for(i = 0; i < r2; i++)
- {
- for(j = 0; j < c2; j++)
- {
- printf("%d\t",matB[i][j]);
- }
- printf("\n");
- }
- break;
- case 3:
- for(i = 0; i < r1; i++)
- {
- for(j = 0; j < c2; j++)
- {
- printf("%d\t",matRes[i][j]);
- }
- printf("\n");
- }
- break;
- }
- }
- // UTILITY FUNCTION: CHECKS IF MATRIX 1 AND MATRIX 2 ARE MULTIPLICABLE
- int checkValidation()
- {
- if(c1!=r2)
- return -1;
- else
- return 1;
- }
- // CORE FUNCTION: READS AND PARSES INPUT TO MATRIX 1 AND MATRIX 2
- void parse2mat()
- {
- FILE *f;
- int i,j;
- f=fopen("input.txt", "r");
- if (f != NULL)
- {
- if(fscanf(f,"%d %d\n",&r1,&c1)!=-1) // READ 2 INTEGERS (R1,C1) FROM THE FIRST LINE, SEPARATED BY A WHITESPACE
- {
- for(i = 0; i < r1; i++) // READ INTEGERS ACCORDING TO THE SIZE OF THE MATRIX (R1,C1)
- {
- for(j = 0; j < c1; j++)
- {
- if (!fscanf(f, "%d", &matA[i][j]))
- break;
- }
- }
- }
- printf("\n\nThe Input Matrix A of dimensions R:%d C:%d:\n",r1,c1);
- printMat(1);
- if(fscanf(f,"%d %d\n",&r2,&c2)!=-1) // READ 2 INTEGERS (R2,C2) FROM THE FIRST LINE, SEPARATED BY A WHITESPACE
- {
- for(i = 0; i < r2; i++) // READ INTEGERS ACCORDING TO THE SIZE OF THE MATRIX (R2,C2)
- {
- for(j = 0; j < c2; j++)
- {
- if (!fscanf(f, "%d", &matB[i][j]))
- break;
- }
- }
- }
- printf("\n\nThe Input Matrix B of dimensions R:%d C:%d:\n",r2,c2);
- printMat(2);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement