C中pthreads的两个矩阵的乘积

时间:2017-03-31 08:30:22

标签: c pointers matrix struct pthreads

我遇到了C Pthreaded程序的问题。我必须做两个矩阵m1(nr1行和nc1列)和m2(nr2行和nc2列)的乘积。 我创建nr1 * nc2线程运行时传递到每个线程的m1行数和m2的列数乘以。线程,将结果保存在另一个matrice中。代码是这样的:

#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        
}

然后我收到了m1和m2的印刷品以及产品的印刷品,如下所示:

   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

但是,在第二部分似乎是m2从未被初始化(即使在1部分中,印刷品说明不同)。

解决: 正确的代码是:

#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        
}

对于ex的输入为5x5和5x5,这个:

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 

2 个答案:

答案 0 :(得分:1)

一个很大的问题是你的动态内存分配,因为你似乎不明白malloc的作用:malloc函数分配了许多字节

例如(来自您的代码):

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

这里为指针分配足够的内存到prodmat结构,而不是实际prodmat 结构的内存。要为prodmat结构分配内存,您应该

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

请注意malloc来电之间的区别?

您对[{1}}的更多通话都遵循相同的错误模式。

如果指针的大小与您要分配的内容不匹配,则可能会分配给很少的内存,并且未定义的行为

至于输出错误的问题,因为您使用了错误的printf格式来打印值。格式malloc用于打印"%i",但数组中的值为int

使用错误的printf格式会导致未定义的行为

答案 1 :(得分:0)

您的printf产品不正确。

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

矩阵中的内容是双精度浮点数,您应该使用%f或其他合适的浮点格式说明符。