【问题标题】:Product of two matrices with pthreads in C两个矩阵与 C 中的 pthread 的乘积
【发布时间】:2017-08-25 10:50:48
【问题描述】:

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

#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 似乎从未被初始化(即使在第一部分中打印说明不同)。

已解决: 正确的代码是这样的:

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

对于 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 

【问题讨论】:

    标签: c pointers matrix struct pthreads


    【解决方案1】:

    您的产品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 或其他合适的浮点格式说明符。

    【讨论】:

    • 对不起!是的,这是 %i 错误!我更新了正确的代码
    • 你是说解决了问题中的问题还是只是一个错字?
    • 修复了程序的所有问题啊啊啊
    • 好的,我不确定是否需要寻找其他问题,但我看到您现在已经接受了我的回答。
    【解决方案2】:

    一个大问题是您的动态内存分配,因为您似乎不明白malloc 做了什么:malloc 函数分配了许多字节

    例如(来自您的代码):

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

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

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

    注意到malloc 调用之间的区别了吗?

    您对malloc 的更多呼叫遵循相同的错误模式。

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


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

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

    【讨论】:

    • 感谢您的回答。我改变了struct prodmat的分配,但问题是一样的。我确信 dmat1 和 dmat2 正确分配了函数 allocM2d。我不知道为什么线程没有正确打印两个矩阵!
    • 如果您更新了问题,您的内存分配仍然大多是错误的。我建议你用 C++ 做你的项目,你可以使用 std::vector 并且你将能够专注于逻辑而不是内存模型。
    • @gabry 如果你打算通过使用不同的语言来解决这个问题,你到底为什么要使用 C++ 而不是更简单的东西?
    • 哦!谢谢,我是笨蛋!这是 %i 错误!抱歉,现在我更新了正确的代码!
    猜你喜欢
    • 2013-03-31
    • 1970-01-01
    • 2019-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多