2 gcc matrixmul.c -o matrixmul -lpthread -Wall -W -Wextra -ansi -pedantic */
19 struct matrix
*mat1
= NULL
;
20 struct matrix
*mat2
= NULL
;
21 struct matrix
*mat3
= NULL
;
29 /* function prototypes */
30 mm_error
matrix_alloc(struct matrix
**mat
, unsigned int rows
, unsigned int cols
);
31 void matrix_free(struct matrix
**mat
);
32 mm_error
matrix_read(const char *path
, struct matrix
**mat
);
33 void matrix_print(const struct matrix
*mat
);
34 void *mulvect(void *arg
);
35 void diep(const char *s
);
37 int main(int argc
, char *argv
[])
40 struct matrix_index
*v
;
41 unsigned int i
, j
, k
, mdepth
= 0, numthreads
;
43 /* check argument count */
45 fprintf(stderr
, "Usage: %s matfile1 matfile2\n", argv
[0]);
49 /* read matrix data from files */
50 if (matrix_read(argv
[1], &mat1
) != mm_error_none
)
51 goto CLEANUP_AND_EXIT
;
54 if (matrix_read(argv
[2], &mat2
) != mm_error_none
)
55 goto CLEANUP_AND_EXIT
;
58 /* is the multiplication feasible by definition? */
59 if (mat1
->cols
!= mat2
->rows
) {
60 fprintf(stderr
, "Matrices' dimensions size must satisfy (NxM)(MxK)=(NxK)\n");
61 goto CLEANUP_AND_EXIT
;
64 /* allocate memory for the result */
65 if (matrix_alloc(&mat3
, mat1
->rows
, mat2
->cols
) != mm_error_none
)
66 goto CLEANUP_AND_EXIT
;
69 /* how many threads do we need ? */
70 numthreads
= mat1
->rows
* mat2
->cols
;
72 /* v[k] holds the (i, j) pair in the k-th computation */
73 if ((v
= malloc(numthreads
* sizeof *v
)) == NULL
) {
75 goto CLEANUP_AND_EXIT
;
79 /* allocate memory for the threads' ids */
80 if ((tid
= malloc(numthreads
* sizeof *tid
)) == NULL
) {
82 goto CLEANUP_AND_EXIT
;
86 /* create the threads */
87 for (i
= 0; i
< mat1
->rows
; i
++) {
88 for (j
= 0; j
< mat2
->cols
; j
++) {
92 if (pthread_create(&tid
[k
], NULL
, mulvect
, (void *)&v
[k
])) {
93 perror("pthread_create");
94 goto CLEANUP_AND_EXIT
;
99 /* make sure all threads are done */
100 for (i
= 0; i
< numthreads
; i
++)
101 if (pthread_join(tid
[i
], NULL
)) {
102 perror("pthread_join");
103 goto CLEANUP_AND_EXIT
;
106 /* print the result */
128 mm_error
matrix_alloc(struct matrix
**mat
, unsigned int rows
, unsigned int cols
)
130 unsigned int i
, j
, mdepth
= 0;
132 *mat
= malloc(sizeof **mat
);
134 goto CLEANUP_AND_RETURN
;
140 (*mat
)->data
= malloc(rows
* sizeof(int *));
141 if ((*mat
)->data
== NULL
)
142 goto CLEANUP_AND_RETURN
;
145 for (i
= 0; i
< rows
; i
++) {
146 (*mat
)->data
[i
] = malloc(cols
* sizeof(int));
147 if ((*mat
)->data
[i
] == NULL
) {
150 goto CLEANUP_AND_RETURN
;
153 return mm_error_none
;
159 for (j
= 0; j
< i
; j
++)
160 free((*mat
)->data
[j
]);
169 return mm_error_no_memory
;
172 void matrix_free(struct matrix
**mat
)
176 for (i
= 0; i
< (*mat
)->rows
; i
++)
177 free((*mat
)->data
[i
]);
182 mm_error
matrix_read(const char *path
, struct matrix
**mat
)
185 unsigned int i
, j
, rows
, cols
;
188 if ((fp
= fopen(path
, "r")) == NULL
) {
189 fprintf(stderr
, "Error opening file: %s\n", path
);
193 /* read matrix dimensions */
194 fscanf(fp
, "%u%u", &rows
, &cols
);
196 /* allocate memory for matrix */
197 if (matrix_alloc(mat
, rows
, cols
) == mm_error_no_memory
) {
199 return mm_error_no_memory
;
202 /* read matrix elements */
203 for (i
= 0; i
< (*mat
)->rows
; i
++) {
204 for (j
= 0; j
< (*mat
)->cols
; j
++) {
205 fscanf(fp
, "%d", &(*mat
)->data
[i
][j
]);
212 return mm_error_none
;
215 void matrix_print(const struct matrix
*mat
)
219 for (i
= 0; i
< mat
->rows
; i
++) {
220 for (j
= 0; j
< mat
->cols
; j
++) {
221 printf("%d ", mat
->data
[i
][j
]);
228 void *mulvect(void *arg
)
230 unsigned int i
, row
, col
;
232 row
= *((int *)arg
+ 0);
233 col
= *((int *)arg
+ 1);
235 mat3
->data
[row
][col
] = 0;
236 for (i
=0; i
<mat1
->cols
; i
++)
237 mat3
->data
[row
][col
] += mat1
->data
[row
][i
] * mat2
->data
[i
][col
];
242 void diep(const char *s
)