并行乘法矩阵 OpenMP 比顺序矩阵慢

parallel multiply matrix openmp is slower than sequential

本文关键字:顺序 OpenMP 并行      更新时间:2023-10-16

我是一个新的OpenMp程序员,现在我在乘以两个矩阵时遇到了问题。这是我的并行代码,但它没有我预期的那么快。 例如,我给它一个 3000 * 3000 矩阵和 3000 * 3000,我的域是 2(随机数是 0 或 1(,并行比顺序慢

clock_t tStart = clock();
cout<<(char)169<<" parallel "<<(char)170<<endl;
int a,b,c,Domain ;
cin>>a>>b>>c>>Domain;
srand(time(0));
int **arr1;
int **arr2;
int **arrRet;
arr1 = new int*[a];
#pragma omp for schedule (dynamic)
for(int i=0 ; i<a ; i++)
arr1[i] = new int [b];
arr2 = new int*[b];
#pragma omp for schedule (dynamic)
for(int i=0 ; i<b ; i++)
arr2[i] = new int [c];
arrRet = new int*[a];
#pragma omp for schedule (dynamic)
for(int i=0 ; i<a ; i++)
arrRet[i] = new int [c];
#pragma omp for schedule (dynamic)
for(int i=0 ; i<a ; i++)
{
#pragma omp for schedule (dynamic)
for(int j=0; j<b ; j++)
{
arr1[i][j]=rand()%Domain;
}
}
//cout<<"nnn";
#pragma omp for schedule (dynamic)
for(int i=0 ; i<b ; i++)
{
#pragma omp for schedule (dynamic)
for(int j=0 ; j<c ; j++)
{
arr2[i][j]=rand()%Domain;
}
}
//cout<<"nnn";
#pragma omp for schedule (dynamic)
for(int i=0 ; i<a ; i++)
#pragma omp for schedule (dynamic)
for(int j2=0 ; j2<c ; j2++)
{
int sum=0;
#pragma omp parallel for shared(sum) reduction(+:sum)
for(int j=0 ; j<b ; j++)
{
sum+=arr1[i][j]*arr2[j][j2];
}
arrRet[i][j2]=sum;
}
printf("Time taken : %.4fsn", (double)(clock() - tStart) / CLOCKS_PER_SEC);

有许多高度优化的线性代数库可以免费使用。我强烈建议您尽可能使用其中之一。

性能下降可能由多种原因引起。以下列表详细介绍了一些最常见的原因:

  • 当每次迭代的工作量完全平衡时,使用schedule(dynamic)。省略子句会将调度设置为static,这更适合这种类型的并行化。

  • 内存分配压力过大。实际上,您不需要为单个矩阵保留多个内存区域。由于程序中的矩阵大小不会更改,因此您可以完美地为每个矩阵使用单个分配。这也提高了数据局部性,因为连续的行在内存中彼此靠近。然后,您可以使用A[ i * b + j ]访问每个元素,其中b是列数。

int *A = (int *) malloc( a * b * sizeof(int) );
  • 在您的代码中,您似乎错过了一个parallel区域。这会导致除最后一个omp for之外的所有都不会由多个线程执行。

  • 使用collapse(2)omp for构造合并到嵌套循环中,如以下示例所示:

#pragma omp for collapse(2)
for( i = 0; i < a; i++ ) {
for( j = 0; j < b; j++ ) {
// your parallel code
}
}