-
Notifications
You must be signed in to change notification settings - Fork 1
/
multiply.c
134 lines (114 loc) · 3.46 KB
/
multiply.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
double** matResult;
double** mat1;
double** mat2;
int matSize1x;
int matSize1y;
int matSize2x;
int matSize2y;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *runner(void *args) {
// set the row that this thread is responsible for
int index = *((int *) args);
double partialSum = 0;
// multiply the row with all columns in matrix_2
for (int j = 0; j < matSize2y; j++) {
for(int i = 0; i < matSize1y; i++) {
partialSum += (mat1[index][i]) * (mat2[i][j]);
}
// set the corresponding row_col of the resulting matrix
pthread_mutex_lock(&mutex);
matResult[index][j] = partialSum;
pthread_mutex_unlock(&mutex);
}
pthread_exit(0);
}
int main(int argc, char **argv) {
// check if arguments were supplied
if (argc <= 2) {
printf("No arguments were passed in...\n");
exit(1);
}
// get the file names from the arguments
char *fileName1 = argv[1];
char *fileName2 = argv[2];
FILE *file;
FILE *file2;
file=fopen(fileName1, "r");
// determine dimensions of the matrix
fscanf(file, "%d", &matSize1x);
fscanf(file, "%d", &matSize1y);
// allocate space for the matrix
mat1=malloc(matSize1x*sizeof(double*));
// allocate the columns
for(int i = 0; i < matSize1x; ++i) {
mat1[i]=malloc(matSize1y*sizeof(double));
}
// read from the file and initialize matrix
for(int i = 0; i < matSize1y; i++)
{
for(int j = 0; j < matSize1y; j++)
{
if (!fscanf(file, "%lf", &mat1[i][j]))
break;
}
}
// close the first file
fclose(file);
// same procedure for the second matrix
file2=fopen(fileName2, "r");
// acquire the dimensions
fscanf(file2, "%d", &matSize2x);
fscanf(file2, "%d", &matSize2y);
mat2=malloc(matSize2x*sizeof(double*));
// exit if two matrices are not compatible for multiplication
if (matSize1y != matSize2x) {
printf("Matrix dimensions do not match for multiplication\n");
exit(1);
}
// allocate space for the second matrix
for(int i = 0; i < matSize2x; ++i) {
mat2[i]=malloc(matSize2y*sizeof(double));
}
// read from the second file
for(int i = 0; i < matSize2x; i++)
{
for(int j = 0; j < matSize2y; j++)
{
if (!fscanf(file, "%lf", &mat2[i][j]))
break;
}
}
fclose(file2);
// array to hold thread ids
pthread_t tids[matSize1x];
// array to specify the row for each thread
int indices[matSize1x];
// initialize the result matrix with its dimensions
matResult = malloc(matSize1x*sizeof(double*));
for(int i = 0; i < matSize1x; i++) {
matResult[i] = malloc(matSize2y*sizeof(double));
}
// populate the indices for the threads
for(int i = 0; i < matSize1x; i++) {
indices[i] = i;
}
// create the threads as much as there is rows in matrix1
for (int i = 0; i < matSize1x; i++) {
pthread_create(&tids[i], NULL, runner, &indices[i]);
}
// join the threads to the main thread
for (int i = 0; i < matSize1x; i++) {
pthread_join(tids[i], NULL);
}
// print the resulting matrix in format
for(int i = 0; i < matSize1x; i++) {
for (int j = 0; j < matSize2y; j++) {
printf("%lf ", matResult[i][j]);
}
printf("\n");
}
return 0;
}