2 gcc matrixmul.c -o matrixmul -lpthread -Wall -W -Wextra -ansi -pedantic */
25 /* function prototypes */
26 mm_error
matrix_alloc(struct matrix
**mat
, unsigned int rows
, unsigned int cols
);
27 void matrix_free(struct matrix
**mat
);
28 mm_error
matrix_read(const char *path
, struct matrix
**mat
);
29 void matrix_print(const struct matrix
*mat
);
30 void *mulvect(void *arg
);
31 void diep(const char *s
);
33 int main(int argc
, char *argv
[])
36 struct matrix_index
*v
;
37 unsigned int i
, j
, k
, mdepth
= 0, numthreads
;
39 /* check argument count */
41 fprintf(stderr
, "Usage: %s matfile1 matfile2\n", argv
[0]);
45 /* read matrix data from files */
46 if (matrix_read(argv
[1], &mat1
) != mm_error_none
)
47 goto CLEANUP_AND_EXIT
;
50 if (matrix_read(argv
[2], &mat2
) != mm_error_none
)
51 goto CLEANUP_AND_EXIT
;
54 /* is the multiplication feasible by definition? */
55 if (mat1
->cols
!= mat2
->rows
) {
56 fprintf(stderr
, "Matrices' dimensions size must satisfy (NxM)(MxK)=(NxK)\n");
57 goto CLEANUP_AND_EXIT
;
60 /* allocate memory for the result */
61 if (matrix_alloc(&mat3
, mat1
->rows
, mat2
->cols
) != mm_error_none
)
62 goto CLEANUP_AND_EXIT
;
65 /* how many threads do we need ? */
66 numthreads
= mat1
->rows
* mat2
->cols
;
68 /* v[k] holds the (i, j) pair in the k-th computation */
69 if ((v
= malloc(numthreads
* sizeof *v
)) == NULL
) {
71 goto CLEANUP_AND_EXIT
;
75 /* allocate memory for the threads' ids */
76 if ((tid
= malloc(numthreads
* sizeof *tid
)) == NULL
) {
78 goto CLEANUP_AND_EXIT
;
82 /* create the threads */
83 for (i
= 0; i
< mat1
->rows
; i
++) {
84 for (j
= 0; j
< mat2
->cols
; j
++) {
88 if (pthread_create(&tid
[k
], NULL
, mulvect
, (void *)&v
[k
])) {
89 perror("pthread_create");
90 goto CLEANUP_AND_EXIT
;
95 /* make sure all threads are done */
96 for (i
= 0; i
< numthreads
; i
++)
97 if (pthread_join(tid
[i
], NULL
)) {
98 perror("pthread_join");
99 goto CLEANUP_AND_EXIT
;
102 /* print the result */
124 mm_error
matrix_alloc(struct matrix
**mat
, unsigned int rows
, unsigned int cols
)
126 unsigned int i
, j
, mdepth
= 0;
128 *mat
= malloc(sizeof **mat
);
130 goto CLEANUP_AND_RETURN
;
136 (*mat
)->data
= malloc(rows
* sizeof(int *));
137 if ((*mat
)->data
== NULL
)
138 goto CLEANUP_AND_RETURN
;
141 for (i
= 0; i
< rows
; i
++) {
142 (*mat
)->data
[i
] = malloc(cols
* sizeof(int));
143 if ((*mat
)->data
[i
] == NULL
) {
146 goto CLEANUP_AND_RETURN
;
149 return mm_error_none
;
155 for (j
= 0; j
< i
; j
++)
156 free((*mat
)->data
[j
]);
165 return mm_error_no_memory
;
168 void matrix_free(struct matrix
**mat
)
172 for (i
= 0; i
< (*mat
)->rows
; i
++)
173 free((*mat
)->data
[i
]);
178 mm_error
matrix_read(const char *path
, struct matrix
**mat
)
181 unsigned int i
, j
, rows
, cols
;
184 if ((fp
= fopen(path
, "r")) == NULL
) {
185 fprintf(stderr
, "Error opening file: %s\n", path
);
189 /* read matrix dimensions */
190 fscanf(fp
, "%u%u", &rows
, &cols
);
192 /* allocate memory for matrix */
193 if (matrix_alloc(mat
, rows
, cols
) == mm_error_no_memory
) {
195 return mm_error_no_memory
;
198 /* read matrix elements */
199 for (i
= 0; i
< (*mat
)->rows
; i
++) {
200 for (j
= 0; j
< (*mat
)->cols
; j
++) {
201 fscanf(fp
, "%d", &(*mat
)->data
[i
][j
]);
208 return mm_error_none
;
211 void matrix_print(const struct matrix
*mat
)
215 for (i
= 0; i
< mat
->rows
; i
++) {
216 for (j
= 0; j
< mat
->cols
; j
++) {
217 printf("%d ", mat
->data
[i
][j
]);
224 void *mulvect(void *arg
)
226 unsigned int i
, row
, col
;
228 row
= *((int *)arg
+ 0);
229 col
= *((int *)arg
+ 1);
231 mat3
->data
[row
][col
] = 0;
232 for (i
= 0; i
< mat1
->cols
; i
++)
233 mat3
->data
[row
][col
] += mat1
->data
[row
][i
] * mat2
->data
[i
][col
];
238 void diep(const char *s
)