0

最近我开始使用 OpenMP。进行涉及在 c++ 中创建的 3d 矩阵作为向量的数值计算,我使用并行 for 循环来加速代码。但它的运行速度比串行代码慢。我在 Windows 7 中使用 Codeblocks 编译代码。代码是这样的。

int main(){
  vector<vector<vector<float> > > Dx; //

/*create 3d array Dx[IE][JE][KE] as vectors*/
  Dx.resize(IE);
  for (int i = 0; i < IE; ++i) {
    for (int j = 0; j < JE; ++j){
      dx[i][j].resize(KE);
    }
  }
  //declare and initialize more matrices like this
  .
  .
  .
  double wtime = omp_get_wtime(); // start time
  //and matrix calculations using parallel for loop 

  #pragma omp parallel for
  for (int i=1; i < IE; ++i ) {
    for (int j=1; j < JE; ++j ) {
      for (int k=1; k < KE; ++k ) {
        curl_h = ( Hz[i][j][k] - Hz[i][j-1][k] - Hy[i][j][k] + Hy[i][j][k-1]);
        idxl[i][j][k] = idxl[i][j][k] + curl_h;
        Dx[i][j][k] = gj3[j]*gk3[k]*dx[i][j][k] 
                    + gj2[j]*gk2[k]*.5*(curl_h + gi1[i]*idxl[i][j][k]);
      }  
    }
  }

  wtime =  omp_get_wtime() - wtime;
}

但是具有并行循环的代码比串行代码运行得慢。有任何想法吗 ?谢谢。

4

1 回答 1

0

循环使用curl_h未声明为线程私有的变量。这既是一个错误,也是您感知到的性能问题的原因:

由于内存中只有一个存储位置curl_h所有线程不断地同时尝试读取和写入它。一个 CPU 内核会将值加载到其缓存中,下一个 CPU 内核将向其发出写入,使第一个 CPU 的缓存无效,当它自己尝试使用时curl_h(读取或写入,两者都需要cacheline 在本地缓存中)。

关键是,硬件提出的只有一个内存位置被称为的激烈伪装curl_h要求它致敬。您在缓存一致性协议中会遇到大量的问题,并让您的内存总线忙于不断地从内存中重新获取相同的缓存行。你所有的线程真正在做的就是争夺那个缓存线。

当然,线程之间的持续竞争是一个大错误,因为没有进程可以确定它当前使用的值实际上是它在上面的语句中计算的值。

因此,只需将正确private()的声明添加到您的omp parallel for语句中,您就可以修复错误和性能问题。

于 2017-02-01T13:26:10.587 回答