1

我正在写一个矩阵乘法程序,我需要检查不同大小的不同矩阵的运行时间。然后我需要将我的代码与 main 中的 pthread 并行化,因此我创建了一个头文件,其中包括初始化和乘法函数,然后我的 main 在一个单独的 .c 文件中,但是当我执行我的程序时,我得到以下错误:

错误:分段错误(核心转储)

请注意,我正在尝试对大小为 1000 的方阵进行矩阵乘法。

这是我的代码:

// mm.h

#ifndef MM_H
#define MM_H

#include <stdlib.h>
#include <time.h>

int SIZE, NTHREADS;
int **A, **B, **C;

void init(int **A, int **B, int **C)
{
    int i, j;

    A = (int**)malloc(SIZE * sizeof(int *));
    for(i = 0; i < SIZE; i++)
        A[i] = malloc(SIZE * sizeof(int));

    B = (int**)malloc(SIZE * sizeof(int *));
    for(i = 0; i < SIZE; i++)
        B[i] = malloc(SIZE * sizeof(int));

    C = (int**)malloc(SIZE * sizeof(int *));
    for(i = 0; i < SIZE; i++)
        C[i] = malloc(SIZE * sizeof(int));

    srand(time(NULL));

    for(i = 0; i < SIZE; i++) {
        for(j = 0; j < SIZE; j++) {
            A[i][j] = rand()%100;
            B[i][j] = rand()%100;
        }
    }
}

void mm(int **A, int **B, int **C)
{
    int i, j, k;

    for(i = 0; i < SIZE; i++) {
        for(j = 0; j < SIZE; j++) {
            C[i][j] = 0;
            for(k = 0; k < SIZE; k++) {
                C[i][j] += A[i][k] * B[k][j];
            }
        }
    }
}

#endif

任何我的主要功能:

// mmserial.c

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "mm.h"

int main(int argc, char* argv[])
{
    int i;

    if(argc != 2)
    {
        printf("Usage: %s <size_of_square_matrix>\n", argv[0]);
        exit(1);
    }

    SIZE = atoi(argv[1]);
    init(A, B, C);

    clock_t begin, end;
    double time_spent;

    begin = clock();

    mm(A, B, C);

    end = clock();

    time_spent = (double)(end - begin) / CLOCKS_PER_SEC;

    printf("Elapsed time: %.2lf seconds.\n", time_spent);

    for(i = 0; i < SIZE; i++)
        free((void *)A[i]);
    free((void *)A);

    for(i = 0; i < SIZE; i++)
        free((void *)B[i]);
    free((void *)B);

    return 0;
}

如果有人可以帮助我克服这个问题,我会很高兴。还有更多的问题,我是否也应该动态分配我的最终矩阵,它将保存乘法的结果值?

4

3 回答 3

2

我一直在寻找最终代码,但没有可用的更新,对于那些对动态分配的矩阵乘法感兴趣的人,这里是最终代码:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void allocate_mem(double*** arr, int rows, int cols);
void deallocate_mem(double*** arr, int n);
void printMatrix(double** a, int rows, int cols);
void printMatrixE(double** a, int rows, int cols);
void multMatrixp(double **A, double **B, double **C,int r1,int c1,int r2,int c2);
void init(double*** a, int rows,int cols);

int main(int argc, char* argv[])
{

   int ro1, co1, ro2, co2;
   double **a, **b, **c;    



//ro1=10;
//co1=10000;
//ro2=10000;
//co2=33;

ro1=atoi(argv[1]);
co1=atoi(argv[2]);
ro2=atoi(argv[3]);
co2=atoi(argv[4]);


init(&a,ro1,co1);
init(&b,ro2,co2);
allocate_mem(&c,ro1,co2);

clock_t begin, end;
double time_spent;
begin = clock();
multMatrixp(a, b, c, ro1, co1, ro2, co2);  
end = clock();
time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
printf("Elapsed time: %.2lf seconds.\n", time_spent);

printMatrix(a,ro1,co1); 
printMatrix(b,ro2,co2); 
printMatrixE(c,ro1,co2); 


deallocate_mem(&a,ro1);
deallocate_mem(&b,ro2);
deallocate_mem(&c,ro1);

    return 0;
}

//______________________________________________________________________________
void allocate_mem(double*** arr, int rows, int cols)
{
  int i;
  *arr = (double**)malloc(rows*sizeof(double*));
  for( i=0; i<rows; i++)
    (*arr)[i] = (double*)malloc(cols*sizeof(double));
} 

//______________________________________________________________________________
void deallocate_mem(double*** arr, int rows){
 int i;
    for (i = 0; i < rows; i++)
        free((*arr)[i]);
    free(*arr); 
}

//______________________________________________________________________________

void init(double*** a, int rows,int cols)
{
   int i, j;

*a= (double**) malloc(rows*sizeof(double*));
for(i=0;i<rows;i++)
(*a)[i]=(double*)malloc(cols*sizeof(double));
    for(i=0;i<rows;i++)
        for(j=0;j<cols;j++)
        (*a)[i][j] = rand()%1000;
}


//______________________________________________________________________________
void printMatrix(double** a, int rows, int cols)
{
    int i, j;
   printf("Matrix[%d][%d]\n",rows,cols);    
   for(i=0;i<rows;i++){
      for(j=0;j<cols;j++)
      printf("%7.1lf ",a[i][j]);
      printf("\n");
   }
   printf("\n");   
}

//______________________________________________________________________________
void printMatrixE(double** a, int rows, int cols)
{
    int i, j;
   printf("Matrix[%d][%d]\n",rows,cols);    
   for(i=0;i<rows;i++){
      for(j=0;j<cols;j++)
      printf("%9.2e ",a[i][j]);
      printf("\n");
   } 
   printf("\n");     
}


//______________________________________________________________________________

void multMatrixp(double **A, double **B, double **C,int ro1,int co1,int ro2,int co2)
{
    int i, j, k;
    for(i = 0; i < ro1; i++) {
        for(j = 0; j < co2; j++) {
            C[i][j] = 0;
            for(k = 0; k < co1; k++) {
                C[i][j] += A[i][k] * B[k][j];
            }
        }
    }
}
于 2016-03-17T18:14:40.303 回答
1

您的代码存在多个问题。以下是您在程序中遇到的问题的解决方案。

首先,您需要为C数组分配空间。tacp已经涵盖了这一点,因此,我将跳过相同的内容。

主要问题来自init(A,B)功能。这里有几个问题。一,A并且B是全局指针,因此,这实际上不需要作为函数参数传递。但是,由于您的代码是为此而设计的,因此您必须合并以下更改

//main function invoking init
init(&A, &B); // Pass references to A and B

脚印init需要修改为

void init(int ***Aptr, int ***Bptr)
{
     int    **A; // Define a local pointer to keep rest of the code intact
     int    **B; // Define a local pointer to keep rest of the code intact
     .....................
     //Rest of your code

     // End of function
     *Aptr = A;
     *Bptr = B;
}

通过这 2 项更改,您的代码应该可以正常工作了。在您之前的实现中,只有 和 的本地副本在函数AB进行了更新,init并且没有反映在实际指针上。因此,当init完成时,AB指向潜在NULL的指针,这是导致分段错误的原因。

这个问题还有另一种解决方案。您可以避免将参数传递给init即转换initinit()并将实现修改为void init(). 这可以正常工作(再次假设C也已分配)

但是,还有一点。最后,您还需要注意删除C数组的内存(假设它是在init函数中分配的)

for(i = 0; i < SIZE; i++)
    free((void *)C[i]);
free((void *)C);

后记:

从编程的角度来看,我觉得你不应该混合全局变量并将这些非常全局的变量作为函数参数传递。范围是全局的,这意味着函数绝对可以访问变量,因此不需要将相同的变量传递给函数。

于 2013-04-12T13:57:58.620 回答
0

C也是一个动态矩阵,但你从来没有为它分配内存,直接将值分配给不存在的内存,所以这就是你有核心转储的原因。您还应该为C.

 void mm(int **A, int **B, int **C)
 {
   int i, j, k;

   for(i = 0; i < SIZE; i++) {
      for(j = 0; j < SIZE; j++) {
        C[i][j] = 0;   ///^^^Need to first allocate space for C
        for(k = 0; k < SIZE; k++) {
            C[i][j] += A[i][k] * B[k][j];
        }
      }
   }
}
于 2013-04-12T13:36:23.370 回答