2 gcc matrixmul.c -o matrixmul -lpthread -Wall -W -Wextra -ansi -pedantic */
8 typedef struct matrix
{
14 typedef struct matrix_index
{
25 matrix_t
*mat1
, *mat2
, *mat3
;
27 /* function prototypes */
28 mmret_t
matrix_alloc(matrix_t
**mat
, unsigned int rows
, unsigned int cols
);
29 void matrix_free(matrix_t
**mat
);
30 mmret_t
matrix_read(const char *path
, matrix_t
**mat
);
31 void matrix_print(const matrix_t
*mat
);
32 void *mulvect(void *arg
);
33 void diep(const char *s
);
35 int main(int argc
, char *argv
[])
39 unsigned int i
, j
, k
, mdepth
= 0, numthreads
;
41 /* check argument count */
43 fprintf(stderr
, "Usage: %s matfile1 matfile2\n", argv
[0]);
47 /* read matrix data from files */
48 if (matrix_read(argv
[1], &mat1
) != MM_OK
)
49 goto CLEANUP_AND_EXIT
;
52 if (matrix_read(argv
[2], &mat2
) != MM_OK
)
53 goto CLEANUP_AND_EXIT
;
56 /* is the multiplication feasible by definition? */
57 if (mat1
->cols
!= mat2
->rows
) {
58 fprintf(stderr
, "Matrices' dimensions size must satisfy (NxM)(MxK)=(NxK)\n");
59 goto CLEANUP_AND_EXIT
;
62 /* allocate memory for the result */
63 if (matrix_alloc(&mat3
, mat1
->rows
, mat2
->cols
) != MM_OK
)
64 goto CLEANUP_AND_EXIT
;
67 /* how many threads do we need ? */
68 numthreads
= mat1
->rows
* mat2
->cols
;
70 /* v[k] holds the (i, j) pair in the k-th computation */
71 if ((v
= malloc(numthreads
* sizeof *v
)) == NULL
) {
73 goto CLEANUP_AND_EXIT
;
77 /* allocate memory for the threads' ids */
78 if ((tid
= malloc(numthreads
* sizeof *tid
)) == NULL
) {
80 goto CLEANUP_AND_EXIT
;
84 /* create the threads */
85 for (i
= 0; i
< mat1
->rows
; i
++) {
86 for (j
= 0; j
< mat2
->cols
; j
++) {
90 if (pthread_create(&tid
[k
], NULL
, mulvect
, (void *)&v
[k
])) {
91 perror("pthread_create");
92 goto CLEANUP_AND_EXIT
;
97 /* make sure all threads are done */
98 for (i
= 0; i
< numthreads
; i
++)
99 if (pthread_join(tid
[i
], NULL
)) {
100 perror("pthread_join");
101 goto CLEANUP_AND_EXIT
;
104 /* print the result */
111 case 3: matrix_free(&mat3
);
112 case 2: matrix_free(&mat2
);
113 case 1: matrix_free(&mat1
);
114 case 0: ; /* free nothing */
120 mmret_t
matrix_alloc(matrix_t
**mat
, unsigned int rows
, unsigned int cols
)
122 unsigned int i
, j
, mdepth
= 0;
124 *mat
= malloc(sizeof **mat
);
126 goto CLEANUP_AND_RETURN
;
132 (*mat
)->data
= malloc(rows
* sizeof(int *));
133 if ((*mat
)->data
== NULL
)
134 goto CLEANUP_AND_RETURN
;
137 for (i
= 0; i
< rows
; i
++) {
138 (*mat
)->data
[i
] = malloc(cols
* sizeof(int));
139 if ((*mat
)->data
[i
] == NULL
) {
142 goto CLEANUP_AND_RETURN
;
150 case 3: for (j
= 0; j
< i
; j
++) free((*mat
)->data
[j
]);
151 case 2: free((*mat
)->data
);
153 case 0: ; /* free nothing */
159 void matrix_free(matrix_t
**mat
)
163 for (i
= 0; i
< (*mat
)->rows
; i
++)
164 free((*mat
)->data
[i
]);
170 mmret_t
matrix_read(const char *path
, matrix_t
**mat
)
173 unsigned int i
, j
, rows
, cols
;
176 if ((fp
= fopen(path
, "r")) == NULL
) {
177 fprintf(stderr
, "Error opening file: %s\n", path
);
181 /* read matrix dimensions */
182 fscanf(fp
, "%u%u", &rows
, &cols
);
184 /* allocate memory for matrix */
185 if (matrix_alloc(mat
, rows
, cols
) == MM_ENOMEM
) {
190 /* read matrix elements */
191 for (i
= 0; i
< (*mat
)->rows
; i
++) {
192 for (j
= 0; j
< (*mat
)->cols
; j
++) {
193 fscanf(fp
, "%d", &(*mat
)->data
[i
][j
]);
203 void matrix_print(const matrix_t
*mat
)
207 for (i
= 0; i
< mat
->rows
; i
++) {
208 for (j
= 0; j
< mat
->cols
; j
++) {
209 printf("%d ", mat
->data
[i
][j
]);
216 void *mulvect(void *arg
)
218 unsigned int i
, row
, col
;
220 row
= *((int *)arg
+ 0);
221 col
= *((int *)arg
+ 1);
223 mat3
->data
[row
][col
] = 0;
224 for (i
= 0; i
< mat1
->cols
; i
++)
225 mat3
->data
[row
][col
] += mat1
->data
[row
][i
] * mat2
->data
[i
][col
];
230 void diep(const char *s
)