Cosmetic changes
[eleutheria.git] / pthreads / matrixmul.c
blob7224ae33bd0a145d41b103aae156e7f0509da44c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <pthread.h>
5 struct matrix {
6 unsigned int rows;
7 unsigned int cols;
8 int **data;
9 };
11 struct matrix_index {
12 unsigned int row;
13 unsigned int col;
16 struct matrix *mat1 = NULL;
17 struct matrix *mat2 = NULL;
18 struct matrix *mat3 = NULL;
20 /* function prototypes */
21 void allocmat(struct matrix **mat, int rows, int cols);
22 void freemat(struct matrix **mat);
23 void readmat(const char *path, struct matrix **mat);
24 void printmat(const struct matrix *mat);
25 void *mulvect(void *arg);
27 int main(int argc, char *argv[]) {
28 pthread_t *tid;
29 struct matrix_index *v;
30 unsigned int i, j, k, numthreads;
32 /* arguments validations */
33 if (argc != 3) {
34 fprintf(stderr, "Incorrect num of args.\nUsage: ./matrixmul matfile1 matfile2\n");
35 exit(EXIT_FAILURE);
38 /* read matrix data from files */
39 readmat(argv[1], &mat1);
40 readmat(argv[2], &mat2);
42 /* Is the multiplication feasible by definition? */
43 if (mat1->cols != mat2->rows) {
44 fprintf(stderr, "Matrices' dimensions size must satisfy (NxM)(MxK)=(NxK)\n");
45 exit(EXIT_FAILURE);
48 /* allocate memory for the result */
49 allocmat(&mat3, mat1->rows, mat2->cols);
51 /* How many threads do we need ?*/
52 numthreads = mat1->rows * mat2->cols;
54 /* v[k] holds the (i, j) pair in the k-th computation */
55 v = malloc(numthreads * sizeof(struct matrix_index));
57 /* allocate memory for the threads' ids */
58 tid = malloc(numthreads * sizeof(pthread_t));
59 if (!tid) {
60 fprintf(stderr, "Error allocating memory\n");
61 exit(EXIT_FAILURE);
64 /* create the threads */
65 for (i=0; i<mat1->rows; i++) {
66 for (j=0; j<mat2->cols; j++) {
67 k = i*mat1->rows + j;
68 v[k].row = i;
69 v[k].col = j;
70 if (pthread_create(&tid[k], NULL, mulvect, (void *)&v[k])) {
71 fprintf(stderr, "pthtrad_create() error\n");
72 exit(EXIT_FAILURE);
77 /* make sure all threads are done */
78 for (i=0; i<numthreads; i++)
79 if (pthread_join(tid[i], NULL)) {
80 fprintf(stderr, "pthread_join() error\n");
81 exit(EXIT_FAILURE);
84 /* print the result */
85 printmat(mat3);
87 /* free matrices */
88 freemat(&mat1);
89 freemat(&mat2);
90 freemat(&mat3);
92 return EXIT_SUCCESS;
95 void allocmat(struct matrix **mat, int rows, int cols) {
96 int i;
98 *mat = malloc(sizeof(struct matrix));
99 if (!*mat) {
100 fprintf(stderr, "Error allocating memory\n");
101 exit(EXIT_FAILURE);
104 (*mat)->rows = rows;
105 (*mat)->cols = cols;
107 (*mat)->data = malloc(rows * sizeof(int *));
108 if (!(*mat)->data) {
109 fprintf(stderr, "Error allocating memory\n");
110 exit(EXIT_FAILURE);
113 for (i=0; i<rows; i++) {
114 (*mat)->data[i] = malloc(cols * sizeof(int));
115 if (!(*mat)->data[i]) {
116 fprintf(stderr, "Error allocating memory\n");
117 exit(EXIT_FAILURE);
122 void freemat(struct matrix **mat) {
123 unsigned int i;
125 for (i=0; i<(*mat)->rows; i++) {
126 free((*mat)->data[i]);
128 free(*mat);
129 *mat = NULL;
132 void readmat(const char *path, struct matrix **mat) {
133 FILE *fp;
134 unsigned int i, j, rows, cols;
136 /* open file */
137 if (!(fp = fopen(path, "r"))) {
138 fprintf(stderr, "Error opening file: %s\n", path);
139 exit(EXIT_FAILURE);
142 /* read matrix dimensions */
143 fscanf(fp, "%u%u", &rows, &cols);
145 /* allocate memory for matrix */
146 allocmat(mat, rows, cols);
148 /* read matrix elements */
149 for (i=0; i<(*mat)->rows; i++) {
150 for (j=0; j<(*mat)->cols; j++) {
151 fscanf(fp, "%d", &(*mat)->data[i][j]);
155 /* close file */
156 fclose(fp);
160 void printmat(const struct matrix *mat) {
161 unsigned int i, j;
163 for (i=0; i<mat->rows; i++) {
164 for (j=0; j<mat->cols; j++) {
165 printf("%d ", mat->data[i][j]);
167 printf("\n");
172 void *mulvect(void *arg) {
173 unsigned int i, row, col;
175 row = *((int *)arg + 0);
176 col = *((int *)arg + 1);
178 mat3->data[row][col] = 0;
179 for (i=0; i<mat1->cols; i++)
180 mat3->data[row][col] += mat1->data[row][i] * mat2->data[i][col];
182 pthread_exit(NULL);