Diego Zucca
Diego Zucca

Reputation: 33

Product of two matrices with pthreads in C

i have a problem with a C Pthreaded program. I have to do the product of two matrices m1 (nr1 rows and nc1 columns) and m2 (nr2 rows and nc2 columns). I create nr1 * nc2 threads run time passing to each thread the number of row of m1 and the number of column of m2 to multiply. The thread, save the result in another matrice. The code is this:

#include <stdio.h>
#include <stdlib.h>
#include "pthread.h"
#include "semaphore.h"



struct prodmat{
int  row;
int  col;
};

int number;
double **dmat1;
double **dmat2;
double **dmatprod;

void ** allocaM2d (int nr, int nc, int dim);
void prodmat(double ** a,  double ** b, double ** c, int nr1, int nc1nr2,
               int nc2);

void * prodthread(struct prodmat * prod){

pthread_detach (pthread_self ());
//printf("THREAD");
 int r,c,k;
 r = prod->row;
 c = prod->col;

 printf("Thread for product of row = %i, column = %i and number = %i\n",r,c,number);


      for (k=0; k<number; k++){
        //dmatprod[r][c] += dmat1[r][k]*dmat2[k][c];
        printf("product of dmat1[%i][%i]=%i * dmat2[%i][%i] = %i\n",r,k,dmat1[r][k],k,c, dmat2[k][c]);     

         }

}


int main(void) {

int  nr1, nc1, nr2, nc2, dim, i, j, k,r,c;


printf("Rows and Columns of the first matrix: ");
scanf ("%d%d",&nr1,  &nc1);
do {
  printf("Rows and Columns of the second matrix\n");
  printf("The number of rows must be equal to nc1 ");
  scanf ("%d%d",&nr2,  &nc2);
} while (nr2 != nc1);




number = nr2;
//  dynamic allocation 

dim = sizeof(double);

dmat1 = (double **) allocaM2d(nr1,  nc1, dim);
dmat2 = (double **) allocaM2d(nr2,  nc2, dim);
dmatprod = (double **) allocaM2d(nr1, nc2, dim);



// in this for i create m1 and m2 and then i print these
k=0;
for(i=0;i<nr1;i++)
  for(j=0;j<nc1;j++)
    dmat1[i][j] = k++;

for(i=0;i<nr1;i++){
  for(j=0;j<nc1;j++)
    printf("%lf ", dmat1[i][j]);
  printf("\n");
}

printf("\n");
k=0;
for(i=0;i<nr2;i++)
  for(j=0;j<nc2;j++)
    dmat2[i][j] = k++;

for(i=0;i<nr2;i++){
  for(j=0;j<nc2;j++)
    printf("%lf ", dmat2[i][j]);
  printf("\n");
}



//This is the cycle where i create the threads
r=0; c=0;
for(r=0; r<nr1 ; r++)
{



  for(c=0; c<nc2; c++){

   struct prodmat * prod; prod= malloc(sizeof(struct prodmat *));
   pthread_t * th; th= malloc(sizeof(pthread_t *)); 

   prod->row = r;
   prod->col = c;

   pthread_create(th,NULL,prodthread,prod);  
  }


}
/*
prodmat( dmat1, dmat2, dmatprod, nr1, nc1, nc2);

printf("\n");
for(i=0;i<nr1;i++){
  for(j=0;j<nc2;j++)
    printf("%lf ", dmatprod[i][j]);
  printf("\n");
}
*/


//is not important this sleep(100). I will replace in future.
sleep(100);
}

/************************************************************/

void ** allocaM2d (int nr, int nc, int dim){
int i;
void ** m;
char * vd;  //  byte pointer

m = (void **) malloc(nr * sizeof(void *));
vd = (char *) malloc(nr * nc * dim);

for(i=0;i<nr;i++)
  m[i] = &vd[i * nc * dim];

return (void **) m; // return matrix pointer        
}

Then i receive the print of the m1 and m2 and the print of the product, something like this:

   0.000000 1.000000 2.000000 3.000000 4.000000 
   5.000000 6.000000 7.000000 8.000000 9.000000 
   10.000000 11.000000 12.000000 13.000000 14.000000 
   15.000000 16.000000 17.000000 18.000000 19.000000 

   0.000000 1.000000 2.000000 3.000000 
   4.000000 5.000000 6.000000 7.000000 
   8.000000 9.000000 10.000000 11.000000 
   12.000000 13.000000 14.000000 15.000000 
   16.000000 17.000000 18.000000 19.000000 

    Thread for product of row = 3, column = 2 and number = 5
    product of dmat1[3][0]=0 * dmat2[2][0] = 0
    product of dmat1[3][1]=1 * dmat2[2][0] = 0
    product of dmat1[3][2]=2 * dmat2[2][0] = 0
    product of dmat1[3][3]=3 * dmat2[2][0] = 0
    product of dmat1[3][4]=4 * dmat2[2][0] = 0

But, in the second part seems like if the m2 is never been initialized (even if in the 1 part the print tells different).

SOLVED: The correct code is this:

#include <stdio.h>
#include <stdlib.h>
#include "pthread.h"
#include "semaphore.h"



struct prodmat{
int  row;
int  col;
};

int number;
double **dmat1;
double **dmat2;
double **dmatprod;

void ** allocaM2d (int nr, int nc, int dim);
void prodmat(double ** a,  double ** b, double ** c, int nr1, int nc1nr2,
               int nc2);

void * prodthread(struct prodmat * prod){

pthread_detach (pthread_self ());
//printf("THREAD");
 int r,c,k;
 r = prod->row;
 c = prod->col;

 //printf("Thread for product of row = %i, column = %i \n",r,c);


      for (k=0; k<number; k++){
        dmatprod[r][c] += dmat1[r][k]*dmat2[k][c];
        //printf("product of dmat1[%i][%i]=%lf * dmat2[%i][%i] = %lf\n",r,k,dmat1[r][k],k,c, dmat2[k][c]);     

         }

  pthread_exit(pthread_self ());

}

void * printer(struct prodmat * prod){

pthread_detach (pthread_self ());
//printf("THREAD");
 int r,c,i,j;
 r = prod->row;
 c = prod->col;

 //printf("Thread for product of row = %i, column = %i \n",r,c);

    printf("\n\n --> PRODUCT: \n\n");
      for(i=0;i<r;i++){
         for(j=0;j<c;j++)
          printf("%lf ", dmatprod[i][j]);
          printf("\n");
         } 

  printf("\n\n ");
  pthread_exit(pthread_self ());

}

int main(void) {

int  nr1, nc1, nr2, nc2, dim, i, j, k,r,c;


printf("Rows and Columns of the first matrix: ");
scanf ("%d%d",&nr1,  &nc1);
do {
  printf("Rows and Columns of the second matrix\n");
  printf("The number of rows must be equal to nc1 ");
  scanf ("%d%d",&nr2,  &nc2);
} while (nr2 != nc1);




number = nr2;
//  dynamic allocation 

dim = sizeof(double);

dmat1 = (double **) allocaM2d(nr1,  nc1, dim);
dmat2 = (double **) allocaM2d(nr2,  nc2, dim);
dmatprod = (double **) allocaM2d(nr1, nc2, dim);

k=0;
for(i=0;i<nr1;i++)
  for(j=0;j<nc1;j++)
    dmat1[i][j] = k++;

for(i=0;i<nr1;i++){
  for(j=0;j<nc1;j++)
    printf("%lf ", dmat1[i][j]);
  printf("\n");
}

printf("\n");
k=0;
for(i=0;i<nr2;i++)
  for(j=0;j<nc2;j++)
    dmat2[i][j] = k++;

for(i=0;i<nr2;i++){
  for(j=0;j<nc2;j++)
    printf("%lf ", dmat2[i][j]);
  printf("\n");
}


r=0; c=0;
for(r=0; r<nr1 ; r++)
{



  for(c=0; c<nc2; c++){

   struct prodmat * prod; prod= malloc(sizeof(struct prodmat));
   pthread_t * th; th= malloc(sizeof(pthread_t )); 

   prod->row = r;
   prod->col = c;

   pthread_create(th,NULL,prodthread,prod);  
  }


}

sleep(1);
 struct prodmat * prod; prod= malloc(sizeof(struct prodmat));
 pthread_t * th; th= malloc(sizeof(pthread_t )); 

 prod->row = nr1;
 prod->col = nc2;

 pthread_create(th,NULL,printer,prod);  

/*
prodmat( dmat1, dmat2, dmatprod, nr1, nc1, nc2);

printf("\n");
for(i=0;i<nr1;i++){
  for(j=0;j<nc2;j++)
    printf("%lf ", dmatprod[i][j]);
  printf("\n");
}
*/


pthread_exit(pthread_self ());



}

/************************************************************/

void ** allocaM2d (int nr, int nc, int dim){
int i;
void ** m;
char * vd;  //  byte pointer

m = (void **) malloc(nr * sizeof(void *));
vd = (char *) malloc(nr * nc * dim);

for(i=0;i<nr;i++)
  m[i] = &vd[i * nc * dim];

return (void **) m; // return matrix pointer        
}

That produces, for an input of 5x5 and 5x5 for ex, this:

0.000000 1.000000 2.000000 3.000000 4.000000 
5.000000 6.000000 7.000000 8.000000 9.000000 
10.000000 11.000000 12.000000 13.000000 14.000000 
15.000000 16.000000 17.000000 18.000000 19.000000 
20.000000 21.000000 22.000000 23.000000 24.000000 

0.000000 1.000000 2.000000 3.000000 4.000000 
5.000000 6.000000 7.000000 8.000000 9.000000 
10.000000 11.000000 12.000000 13.000000 14.000000 
15.000000 16.000000 17.000000 18.000000 19.000000 
20.000000 21.000000 22.000000 23.000000 24.000000 


 --> PRODUCT: 

150.000000 160.000000 170.000000 180.000000 190.000000 
400.000000 435.000000 470.000000 505.000000 540.000000 
650.000000 710.000000 770.000000 830.000000 890.000000 
900.000000 985.000000 1070.000000 1155.000000 1240.000000 
1150.000000 1260.000000 1370.000000 1480.000000 1590.000000 

Upvotes: 0

Views: 126

Answers (2)

JeremyP
JeremyP

Reputation: 86661

Your printf for the products is incorrect.

printf("product of dmat1[%i][%i]=%i * dmat2[%i][%i] = %i\n",r,k,dmat1[r][k],k,c, dmat2[k][c]);
//                                ^ wrong              ^ wrong

The contents in your matrices are double precision floating point numbers, you should use %f or other suitable floating point format specifier.

Upvotes: 1

Some programmer dude
Some programmer dude

Reputation: 409356

A big problem is your dynamic memory allocations, as it seems you don't understand what malloc does: The malloc function allocates a number of bytes.

For example (from your code):

struct prodmat * prod; prod= malloc(sizeof(struct prodmat *));

Here you allocate enough memory for a pointer to a prodmat structure, not memory for an actual prodmat structure. To allocate memory for a prodmat structure you should do

struct prodmat * prod; prod= malloc(sizeof(struct prodmat));

Notice the difference between the malloc calls?

More of your calls to malloc follow the same wrong pattern.

If the size of a pointer does not match what you intend to allocate you might allocate to little memory, and have undefined behavior.


As for the problem with the output being wrong, it's because you use the wrong printf format to print the values. The format "%i" is for printing int, but the values in the arrays are double.

Using the wrong printf format leads to undefined behavior.

Upvotes: 1

Related Questions