尝试将尺寸为1000 * 1000的两个大矩阵相乘会导致分段错误

时间:2018-08-06 10:26:14

标签: c linux matrix

尝试将维度为1000*1000的两个矩阵相乘。但是,尝试这样做会导致Segmentation fault。是什么原因造成的?如何解决?

#include <stdio.h>
#include<stdlib.h>
#include<time.h>
int main()
{
clock_t t;
    t = clock();
   long int a[1000][1000], b[1000][1000], result[1000][1000], r1=1000, c1=1000, r2=1000, c2=1000, i, j, k;

   // Column of first matrix should be equal to column of second matrix and
  /*  while (c1 != r2)
    {
        printf("Error! column of first matrix not equal to row of second.\n\n");
        printf("Enter rows and column for first matrix: ");
        scanf("%d %d", &r1, &c1);
        printf("Enter rows and column for second matrix: ");
        scanf("%d %d",&r2, &c2);
    }
*/

    // Storing elements of first matrix.
    printf("\nEnter elements of matrix 1:\n");
    for(i=0; i<r1; ++i)
        for(j=0; j<c1; ++j)
        {
          a[i][j]=rand()%20;
        }

    // Storing elements of second matrix.
    printf("\nEnter elements of matrix 2:\n");
    for(i=0; i<r2; ++i)
        for(j=0; j<c2; ++j)
        {
            b[i][j]=rand()%20;
        }

    // Initializing all elements of result matrix to 0
    for(i=0; i<r1; ++i)
        for(j=0; j<c2; ++j)
        {
            result[i][j] = 0;
        }

    // Multiplying matrices a and b and
    // storing result in result matrix
    for(i=0; i<r1; ++i)
        for(j=0; j<c2; ++j)
            for(k=0; k<c1; ++k)
            {
                result[i][j]+=a[i][k]*b[k][j];
            }
 // Displaying the result
    printf("\nOutput Matrix:\n");
    for(i=0; i<r1; ++i)
        for(j=0; j<c2; ++j)
        {
            printf("%ld  ", result[i][j]);
            if(j == c2-1)
                printf("\n\n");
        }
t = clock() - t;
    double time_taken = ((double)t)/CLOCKS_PER_SEC; // in seconds

    printf("\n \nfunction took %f seconds to execute \n", time_taken);
    return 0;
}

2 个答案:

答案 0 :(得分:4)

在有大量内存分配的情况下,您需要使用动态内存分配。堆栈内存无法满足这些大内存需求。

您可以使用动态内存分配解决此问题。尝试:-

[root@g9csf0002-0-0-12 kafka]# java -version
openjdk version "1.8.0_181"
OpenJDK Runtime Environment (build 1.8.0_181-b13)
OpenJDK 64-Bit Server VM (build 25.181-b13, mixed mode) 

然后使用:-

访问元素
int (*a)[r1][c1] = malloc(sizeof *a);
int (*b)[r2][c2] = malloc(sizeof *b);
int (*result)[r1][c2] = malloc(sizeof *result);

尝试此代码:-

(*result)[i][j] ;
(*a)[i][k] ;
(*b)[k][j] ;

输出:-

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
    clock_t t;
    t = clock();
    int r1 = 1000, c1 = 1000, r2 = 1000, c2 = 1000, i, j, k;

    // Dynamic allocation.

    int(*a)[r1][c1] = malloc(sizeof *a);
    int(*b)[r2][c2] = malloc(sizeof *b);
    int(*result)[r1][c2] = malloc(sizeof *result);

    // Storing elements of first matrix.
    printf("\nEnter elements of matrix 1:\n");
    for (i = 0; i < r1; ++i)
    {
        for (j = 0; j < c1; ++j)
        {
            (*a)[i][j] = rand() % 20;
        }
    }

    // Storing elements of second matrix.
    printf("\nEnter elements of matrix 2:\n");

    for (i = 0; i < r2; ++i)
    {
        for (j = 0; j < c2; ++j)
        {
            (*b)[i][j] = rand() % 20;
        }
    }
    // Initializing all elements of result matrix to 0
    for (i = 0; i < r1; ++i)
    {
        for (j = 0; j < c2; ++j)
        {
            (*result)[i][j] = 0;
        }
    }
    // Multiplying matrices a and b and
    // storing result in result matrix
    for (i = 0; i < r1; ++i)
        for (j = 0; j < c2; ++j)
            for (k = 0; k < c1; ++k)
            {
                (*result)[i][j] += (*a)[i][k] * (*b)[k][j];
            }
    // Displaying the result
    printf("\nOutput Matrix:\n");
    for (i = 0; i < r1; ++i)
        for (j = 0; j < c2; ++j)
        {
            printf("%d  ", (*result)[i][j]);
            if (j == c2 - 1)
                printf("\n\n");
        }
    t = clock() - t;
    double time_taken = ((double)t) / CLOCKS_PER_SEC; // in seconds

    printf("\n \nfunction took %f seconds to execute \n", time_taken);

    free(a);
    free(b);
    free(result);
    return 0;
}

注意:由于太大,因此无法包含完整输出。

别忘了释放已分配的内存。

答案 1 :(得分:2)

首先,不分配如此大量的内存作为局部函数变量。与堆的大小相比,它们的存储位置(通常是堆栈)相对较小。您只需要用完自动变量存储即可。而是动态分配它

int *a = malloc(r1 * c1 * sizeof(*a));
int *b = malloc(r2 * c2 * sizeof(*b));
int *result = malloc(r2 * c2 * sizeof(*result));

printf("\nEnter elements of matrix 1:\n");
for(i=0; i<r1; ++i)
    for(j=0; j<c1; ++j)
    {
      a[i * c1 + j]=rand()%20;
    }


....

您可以使用另一种分配策略来获得更自然的索引。