通过控制台设置线程数时,Openmp分段错误

时间:2016-05-09 21:25:11

标签: c multithreading openmp

我有使用openmp的矩阵乘法代码:

#include <stdio.h>
#include <omp.h>
#include <math.h>
#define N 1000
int main()
{
    long int i, j, k;
    //long int N = atoi(argv[1]);
    double t1, t2;
    double a[N][N],b[N][N],c[N][N]; 

    for (i=0; i<N; i++)
        for (j=0; j<N; j++)
            a[i][j]=b[i][j]=log(i*j/(i*j+1.)+1) +exp(-(i+j)*(i+j+1.));

    t1=omp_get_wtime();

    #pragma omp parallel for shared(a, b, c) private(i, j, k)
    for(i=0; i<N; i++){
        for(j=0; j<N; j++){
            c[i][j] = 0.0;
            for(k=0; k<N; k++) c[i][j]+=a[i][k]*b[k][j];
        }
    }

    t2=omp_get_wtime();
    printf("Time=%lf\n", t2-t1);
}

现在我想通过命令行设置我想要的线程数。我是通过使用

来做到的
atoi(argv[])

#include <stdio.h>
#include <omp.h>
#include <math.h>
#define N 1000
int main(int argc, char** argv[])
{
    long int i, j, k;
    //long int N = atoi(argv[1]);
    double t1, t2;
    double a[N][N],b[N][N],c[N][N];

    for (i=0; i<N; i++)
        for (j=0; j<N; j++)
            a[i][j]=b[i][j]=log(i*j/(i*j+1.)+1) +exp(-(i+j)*(i+j+1.));

    int t = atoi(argv[1]);
    t1=omp_get_wtime();

    #pragma omp parallel for shared(a, b, c) private(i, j, k) num_threads(t)
    for(i=0; i<N; i++){
        for(j=0; j<N; j++){
            c[i][j] = 0.0;
            for(k=0; k<N; k++) c[i][j]+=a[i][k]*b[k][j];
        }
    }

    t2=omp_get_wtime();
    printf("Time=%lf\n", t2-t1);
}

一切都很好,除了一件至关重要的事情:当我尝试计算尺寸大于(或多或少)500的矩阵的乘积时,我得到了错误:&#34;分段错误&#34;。有人可以澄清这个错误的原因吗?

1 个答案:

答案 0 :(得分:1)

我对openmp一无所知,但你肯定会炸毁你的筹码。默认堆栈空间因系统而异,但对于N == 1000,您试图在堆栈上放置三个总共300万double的2D阵列。假设double是8个字节,那是2400万字节,或者只是22.9MB。不能有许多系统允许这种堆栈空间。相反,我建议尝试从堆中获取大量内存。像这样:

//double a[N][N],b[N][N],c[N][N];
double **a, **b, **c;
a = malloc(sizeof(double*) * N);
b = malloc(sizeof(double*) * N);
c = malloc(sizeof(double*) * N);

for (i=0; i<N; i++)
{
  a[i] = malloc(sizeof(double) * N);
  b[i] = malloc(sizeof(double) * N);
  c[i] = malloc(sizeof(double) * N);
}

// do your calculations

for (i=0; i<N; i++)
{
  free(a[i]);
  free(b[i]);
  free(c[i]);
}
free(a);
free(b);
free(c);

我至少在我的计算机上验证过,N == 1000尝试将这些数组放在堆栈上时,EXC_BAD_ACCESS使用select * from sys.databases where name = '<your_db>' and source_database_id is not null 崩溃了。当我如上所示动态分配内存时,我没有遇到seg错误。