我有使用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=%lfn", 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=%lfn", t2-t1);
}
一切都很好,除了一件至关重要的事情:当我试图计算维度大于(或多或少)500的矩阵的乘积时,我会得到错误:"分割错误"。有人能澄清这个错误的原因吗?
我对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
崩溃。当我按照上面所示的方式动态分配内存时,我不会出现seg错误。