并行乘法矩阵openmp比顺序慢

时间:2017-08-14 06:44:46

标签: c++ parallel-processing openmp

我是一个新的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<<"\n\n\n";
    #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<<"\n\n\n";
    #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 : %.4fs\n", (double)(clock() - tStart) / CLOCKS_PER_SEC);

1 个答案:

答案 0 :(得分:0)

有许多高度优化的linear algebra libraries可以免费使用。我强烈建议你尽可能使用其中一种。

您的性能下降可能有很多原因。以下列表详细介绍了一些最常见的原因:

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

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

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

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

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