2017-08-14 52 views
0

我是一个新的OpenMp Programer,现在我遇到了乘以两个矩阵的问题。这是我的并行代码,但速度并不像我想象的那么快。 例如我给它一个3000 * 3000矩阵和3000 * 3000和我的域为2(随机数为0或1)和并行慢于顺序并行乘法矩阵openmp比序列更慢

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

的可能的复制[OpenMP的时间和时钟()计算两个不同的结果](HTTPS:/ /stackoverflow.com/questions/10673732/openmp-time-and-clock-calculates-two-different-results)和https://stackoverflow.com/q/10624755/620382 – Zulan

+1

不要自己做矩阵乘法。这太疯狂了。矩阵乘法是本书中最古老的问题。找一些图书馆为你做这些,比如OpenBLAS。也可以使用[Armadillo](http://arma.sourceforge.net/)来保存矩阵。停止保留这些不良阵列以保存矩阵。它们很慢,因为你的编译器不能[矢量化](https://en.wikipedia.org/wiki/Automatic_vectorization)它们。您可以将Armadillo与OpenBLAS连接起来,它可以为您和您的处理器功能进行并行处理,从而为您提供最佳性能。 –

+0

@TheQuantumPhysicist我的老师告诉我我不能使用库:( – ali

回答

0

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

您的性能下降可能由许多原因产生。下面详细列举了一些最常见的原因:

  • 使用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 
    } 
}