【问题标题】:Segmentation fault when two matrices size are over 800*800 [duplicate]两个矩阵大小超过800 * 800时的分段错误[重复]
【发布时间】:2018-03-18 20:50:32
【问题描述】:

我正在尝试为整数数据类型编写一个向量乘加“axpy”算法的超级简单的 C 程序。程序输出执行时间来衡量机器的性能。矩阵由随机数填充。

int benchmark(void) {
    int N;      /* The matrix size, controlled by user input */
    int r, c;   /* Row and Column number */
    int random; /* Random number to fill the matix */
    int a = rand() % 20; /* Scale number to multiply x matrix */

    printf("Enter the size(N*N) of the matrices(Maximum 1,000,000)\n");
    scanf("%d", &N);

    if (N > 1000000) {
        fprintf(stderr, "Size of matrix is too large!\n");
        return 0;
    }

    /* Initialize and fill the matrix x and y */
    int xMatrix[N][N], yMatrix[N][N], resultMatrix[N][N];

    /* Compute time */
    clock_t t;

    t = clock();

    for (r = 0; r < N; r++) {
        for (c = 0; c < N; c++) {
            random = rand() % 100;
            xMatrix[r][c] = a * random; /* Multiply matrix x with random value a */
        }
    }
    for (r = 0; r < N; r++) {
        for (c = 0; c < N; c++) {
            int random = rand() % 100;
            yMatrix[r][c] = random;
        }
    }

    /* Add two matrix together */
    for (r = 0; r < N; r++) {
        for (c = 0; c < N; c++) {
            resultMatrix[r][c] = xMatrix[r][c] + yMatrix[r][c];
        }
    }

    t = clock() - t;

    double timeTaken = ((double)t) / CLOCKS_PER_SEC;
    printf("\n -> Total time : %f seconds\n", timeTaken);
    printf("\n -> Vector length : %d", N * N);

}

用户控制矩阵的大小。 当N 的值小于800 时,程序运行良好。

【问题讨论】:

  • 您的堆栈可能已用完。考虑使用 malloc 动态分配数组。
  • 800*800=640,000。 x4(整数大小)= 3,200,000。这是作为局部变量分配的很多内存,它可能由于堆栈空间不足而失败。而是把它放在堆上。

标签: c arrays segmentation-fault


【解决方案1】:

使用自动存储(在堆栈上)分配的对象的大小太大,您会得到未定义的行为,更具体地说是堆栈溢出

您应该改为从堆中分配对象:

    /* Initialize and fill the matix x and y */
    int (*xMatrix)[N] = malloc(N * sizeof(*xMatrix));
    int (*yMatrix)[N] = malloc(N * sizeof(*yMatrix));
    int (*resultMatrix)[N] = malloc(N * sizeof(*resultMatrix));

并验证malloc()返回的指针都不是NULL

这里是修改后的代码:

int benchmark(void) {
    int N;       /* The matrix size, controlled by user input */
    int r, c;    /* Row and Column number */
    int random;  /* Random number to fill the matix */
    int a = rand() % 20; /* Scale number to multiply x matrix */

    printf("Enter the size(N*N) of the matrices (Maximum 1,000,000)\n");
    if (scanf("%d", &N) != 1) {
        fprintf(stderr, "Input error!\n");
        return 0;
    }

    if (N > 1000000) {
        fprintf(stderr, "Matrix size is too large!\n");
        return 0;
    }

    /* Initialize and fill the matrix x and y */
    int (*xMatrix)[N] = malloc(N * sizeof(*xMatrix));
    int (*yMatrix)[N] = malloc(N * sizeof(*yMatrix));
    int (*resultMatrix)[N] = malloc(N * sizeof(*resultMatrix));

    if (xMatrix == NULL || yMatrix == NULL || resultMatrix == NULL) {
        fprintf(stderr, "Memory allocation failed!\n");
        free(xMatrix);
        free(yMatrix);
        free(resultMatrix);
        return 0;
    }

    /* Compute time */
    clock_t t = clock();

    for (r = 0; r < N; r++) {
        for (c = 0; c < N; c++) {
            random = rand() % 100;
            xMatrix[r][c] = a * random; /* Multiply matrix x with random value a */
        }
    }
    for (r = 0; r < N; r++) {
        for (c = 0; c < N; c++) {
            random = rand() % 100;
            yMatrix[r][c] = random;
        }
    }

    /* Add two matrix together */
    for (r = 0; r < N; r++) {
        for (c = 0; c < N; c++) {
            resultMatrix[r][c] = xMatrix[r][c] + yMatrix[r][c];
        }
    }

    t = clock() - t;

    double timeTaken = ((double)t) / CLOCKS_PER_SEC;
    printf("\n -> Total time : %f seconds\n", timeTaken);
    printf("\n -> Vector length : %lld", (long long)N * N);

    free(xMatrix);
    free(yMatrix);
    free(resultMatrix);
    return 0;
}

但是请注意,您的计算非常简单,大部分时间可能都花在了rand() 函数上。

【讨论】:

  • 哈哈,不敢相信大部分时间都浪费在 rand() 上
  • 顺便说一句,*xMatrix[r] = (int *) malloc(N * sizeof(int)) 会导致error: incompatible types when assigning to type ‘int[(sizetype)(N)]’ from type ‘int *’
  • @zuolizhu:当然可以,但是我的帖子里没有这样的代码。 xMatrix 是由N ints 指向N 的二维数组的指针,通过对malloc() 的一次调用分配。
  • 哦,是的,这很有道理!非常感谢!
【解决方案2】:

您正在尝试动态分配内存,我建议您使用 stdlib.h 中的 ma​​lloc,如下所示。

另外,请查看这些 SO 帖子:memory allocation in Stack and HeapWhat and where are the stack and heap?

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

int benchmark(void) {
    int N;  /* The matrix size, controlled by user input */
    int r, c; /* Row and Column number */
    int random; /* Random number to fill the matix */
    int a = rand() % 20; /* Scale number to multiply x matrix */

    printf("Enter the size(N*N) of the matrixs(Maximum 1,000,000)\n");
    scanf("%d", &N);

    if(N > 1000000) {
        fprintf(stderr, "Size of matrix is too large!\n");
        return 0;
    }

    /* Initialize and fill the matix x and y */
    int** xMatrix = NULL;
    int** yMatrix = NULL;
    int** resultMatrix = NULL;

    /* Using the heap memory allocation instead of the stack */
    xMatrix = (int **) malloc(N * sizeof(int *));
    yMatrix = (int **) malloc(N * sizeof(int *));
    resultMatrix = (int **) malloc(N * sizeof(int *));
    for (r = 0; r < N; r++) {
        xMatrix[r] = (int *) malloc(N * sizeof(int));
        yMatrix[r] = (int *) malloc(N * sizeof(int));
        resultMatrix[r] = (int *) malloc(N * sizeof(int));
    }

    /* Compute time */
    clock_t t;

    t = clock();

    for (r = 0; r < N; r++) {
        for (c = 0; c < N; c++) {
            random = rand() % 100;
            xMatrix[r][c] = a * random; /* Multiply matix x with random value a */
        }
    }
    for (r = 0; r < N; r++) {
        for (c = 0; c < N; c++) {
            int random = rand() % 100;
            yMatrix[r][c] = random;
        }
    }

    /* Add two matrix together */
    for (r = 0; r < N; r++) {
        for (c = 0; c < N; c++) {
            resultMatrix[r][c] = xMatrix[r][c] + yMatrix[r][c];
        }
    }

    t = clock() - t;

    double timeTaken = ((double)t)/CLOCKS_PER_SEC;
    printf("\n -> Total time : %f seconds\n", timeTaken);
    printf("\n -> Vector length : %d", N*N);

    /* Always remember to free your allocated memory */
    for (r = 0; r < N; r++) {
        free(xMatrix[r]);
        free(yMatrix[r]);
        free(resultMatrix[r]);
    }
    free(xMatrix);
    free(yMatrix);
    free(resultMatrix);

}

int main() {
    benchmark();
    return 0;
}

【讨论】:

  • 它对我有用!非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-02
相关资源
最近更新 更多