My professor assigned a problem from our OS book about matrix multiplication. Its pretty simple as the book shows how to do most of it. But now my professor has added an extra layer of difficulty. Instead of declaring the multidimensional arrays globally he wants us to input the size of the matricies at runtime such as project.pp row column row column low high. the low and high numbers are the numbers that will be used to fill the two matricies with random numbers between low and high. after matrix A and B are computed these matricies are multiplied to create matrix C. The problem I am having is how to get these arrays to my threads because I can only pass a struct to the thread when it is created. My code so far is below, I could really use a push in the right direction as i'm pretty stuck right now. I am also using a unix server to create this on.

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;

struct v {
   int i; /* row */
   int j; /* column */
   int x;
};

struct matrixProp {
   int row;
   int column;
   int high;
   int low;
};

void *runner(void *param); /* the thread */

void *matrixA (void *prop);
void *matrixB (void *prop);

int main(int argc, char *argv[]) {
   int w,x,y,z,high,low;
    if (argc > 6)
        {
        cout <<"You specified more than six arguments."<< endl;
        cout <<"Additional parameters will be ignored"<< endl;
        }

        else if (argc < 6)
    {
       cout <<"You did not specify enough arguments"<< endl;
       exit(0);
    }

   w = atoi(argv[1]);
   x = atoi(argv[2]);
   y = atoi(argv[3]);
   z = atoi(argv[4]);
   high = atoi(argv[5]);
   low = atoi(argv[6]);

   int A[w][x];
   int B[y][z];
   int C[w][z];

   struct matrixProp *matA = (struct matrixProp *) malloc(sizeof(struct matrixProp));
   matA->high = high;
   matA->low = low;
   matA->row = w;
   matA->column = x;

   /* Now create the thread A */
  pthread_t tid;       //Thread ID
   pthread_attr_t attr; //Set of thread attributes
   //Get the default attributes
   pthread_attr_init(&attr);
   //Create thread
   pthread_create(&tid,&attr,matrixA,matA);

   struct matrixProp *matB = (struct matrixProp *) malloc(sizeof(struct matrixProp));
   matB->high = high;
   matB->low = low;
   matB->row = y;
   matB->column = z;
   pthread_attr_init(&attr);
   //Create thread
   pthread_create(&tid,&attr,matrixB,matB);

   int i,j, count = 0;
   for(i = 0; i < w; i++) {
      for(j = 0; j < z; j++) {
             //struct to pass parameters
         struct v *data = (struct v *) malloc(sizeof(struct v));
         data->i = i; //row
         data->j = j; // column
         data->x = x;
         /* Now create the thread passing it data as a parameter */
         pthread_t tid;       //Thread ID
         pthread_attr_t attr; //Set of thread attributes
         //Get the default attributes
         pthread_attr_init(&attr);
         //Create thread
         pthread_create(&tid,&attr,runner,data);
         //Parent waits for all threads to finish
         pthread_join(tid, NULL);
         count++;
      }
   }

   //print matrix C
   for(i = 0; i < w; i++) {
      for(j = 0; j < z; j++) {
         printf("%d ", C[i][j]);
      }
      printf("\n");
   }
}

//thread is created with parameters from matrix A & B
void *runner(void *param) {
   struct v *data = (v*)param;
   int n, x, sum = 0; // n is counter and sum stores calculation
   x = data->x;
   //Row X Column
   for(n = 0; n< x; n++){
      sum += A[data->i][n] * B[n][data->j];
   }
   //store the sum in its cell in matrix C
   C[data->i][data->j] = sum;

   //exit without error
   pthread_exit(0);
}

void *matrixA(void *prop) {
   struct matrixProp *matA = (matrixProp*)prop;
   int i, j, row, column, high, low, cell = 0;

   row = matA->row;
   column = matA->column;
   high = matA->high;
   low = matA->low;
   //Row X Column
   for(i = 0; i < row; i++) {
      for(j=0; j < column; j++); {
             cell = rand() % high + low;
             A[i][j] = cell;
          }

   }
   //store the sum in its cell in matrix C
     //exit without error
   pthread_exit(0);
}

void *matrixB(void *prop) {
   struct matrixProp *matB = (matrixProp*)prop;
   int i, j, row, column, high, low, cell = 0;

   row = matB->row;
   column = matB->column;
   high = matB->high;
   low = matB->low;
   //Row X Column
   for(i = 0; i < column; i++) {
      for(j=0; j < row; j++); {
             cell = rand() % high + low;
             B[i][j] = cell;
          }

   }
     //exit without error
   pthread_exit(0);
}

I'm not really sure if I understand your problem, because as far as I can see you are already have all of the knowledge to solve it.

Your question is how to pass the two matrices to the thread that is going to multiply them. And you say that you can only pass a struct.
I think that already solves your problem? You can put anything that the runner function needs in a structure, and then pass it to pthread_create.

Also a general comment on your code, you do almost no error checking. What happens if malloc can't allocate the memory you're requesting? Or what if one of the pthread_create functions fail? I assisted in a course on Operating Sytems at my university, a lot of points were deducted for these kinds of errors.
It is _very_ important to always check return values of functions.

Thanks for the tip I've added some error handling to my program now. I'm kind of new to OS programming, is this acceptable error handling?

int error;
error = pthread_create(&tid,&attr,runner,data);
if(error) {
   printf("pthread_create error code at %d: %d %s\n", i, error,
   strerror(error));
   pthread_exit(error);
}

And I understand what your saying that I could have matrix A and B in a struct and pass that to the thread to compute C. But I am still working on how to get A and B. The way I have it now i get the command line arguments and then create array int A[row][column] and same for B. but then how do I pass these arrays to the thread that will generate random numbers to populate them? Also I can't have them initially defined in the struct as A[][] or A[row][column] as this generates errors. is there a way to add them to a struct after allocating the space for them?

No, your error handling is not exactly correct. I've seen many of our students do the same as you did though.

What exactly is pthread_exit meant for? To exit _from_ a posix thread. But in your case the thread that calls pthread_create is not a posix thread. So you can just exit();

Also, there is a special output file descriptor for error messages, called stderr. It is better to print errors to this, instead of to stdout like you are doing now. You can use fprintf for that.

Now on to your array problem. You need to understand that an array in C is basically a pointer. When you write int A[x]; where x is initialized as atio(argv[1]); you are using a feature from C99, you should make sure that your teacher agrees with this.

I think your teachers intention is that you use malloc to allocate a 2D array, and pass that to the functions. I will show you how to do it with a 1D array then it's up to you to extend this to 2D.

// in main:
int* A = (int*)malloc( x * sizeof(int) ); 

pthread_create(&tid,&attr,matrixA, (void*) A);

// in matrixA
... matrixA( void* param ) {
    int* A = (int*)param;
    // use A here 
}

If you want to pass a struct to the thread:

typedef struct threadArgs {
    int* matrixA;
    int* matrixB;
} threadArgs_t;

int main() {
 // creating matrix A and B

 threadArgs_t threadArgs;
 threadArgs.matrixA = A;
 threadArgs.matrixB = B;

 pthread_create(&tid,&attr,runner,(void*)&threadArgs);

 // In runner:
 .. runner( void* param ) {
    threadArgs_t* threadArgs = (threadArgs_t*)param;
    param->matrixA; // etc.
}

I think now you should be able to go ahead ;)

* Please note, my code may contain typos, I did not attempt to compile it.
And, of course you need to do the error checking

Edited 5 Years Ago by thelamb: n/a

Comments
Great help.
helped me a lot

thanks lamb, I think I got it from here. The 2D array was harder to get going than I thought but I have it working now. Thanks again

Q1. Write a file based C Program for matrix multiplication using pthread multithreading.
please if u have the answer send me i really need it please.

Edited 1 Year Ago by pritaeas: Removed email. Keep it on-site.

This article has been dead for over six months. Start a new discussion instead.