OpenMP大大减慢了循环速度

时间:2013-09-11 19:18:57

标签: c performance for-loop parallel-processing openmp

我试图通过OpenMP并行化来加速这个for循环。我的印象是,这应该分散了许多线程的工作。但是,也许开销太大,不能给我任何加速。

我应该提到这个循环发生了很多次,并且循环的每个实例都应该并行化。循环迭代次数newNx可以小到3或大到256.但是,如果我有条件地将它并行化仅用于newNx> 100(只有最大的循环),它仍然显着减慢。

这里有什么东西会导致这比预期慢吗?我还应该提到矢量A,v,b非常大,但是我相信访问是O(1)。

    #pragma omp parallel for private(j,k),shared(A,v,b)
    for(i=1;i<=newNx;i+=2) {
      for(j=1;j<=newNy;j++) { 
        for(k=1;k<=newNz;k+=1) {

          nynz=newNy*newNz; 

          v[(i-1)*nynz+(j-1)*newNz+k] = 
          -(v[(i-1)*nynz+(j-1)*newNz+k+1 - 2*(k/newNz)]*A[((i-1)*nynz + (j-1)*newNz + (k-1))*spN + kup+offA] + 
          v[(i-1)*nynz+(j-1)*newNz+ k-1+2*(1/k)]*A[((i-1)*nynz + (j-1)*newNz + (k-1))*spN + kdo+offA] + 
          v[(i-1)*nynz+(j - 2*(j/newNy))*newNz+k]*A[((i-1)*nynz + (j-1)*newNz + (k-1))*spN + jup+offA] + 
          v[(i-1)*nynz+(j-2 + 2*(1/j))*newNz+k]*A[((i-1)*nynz + (j-1)*newNz + (k-1))*spN + jdo+offA] + 
          v[(i - 2*(i/newNx))*nynz+(j-1)*newNz+k]*A[((i-1)*nynz + (j-1)*newNz + (k-1))*spN + iup+offA] + 
          v[(i-2 + 2*(1/i))*nynz+(j-1)*newNz+k]*A[((i-1)*nynz + (j-1)*newNz + (k-1))*spN + ido+offA] - 
          b[(i-1)*nynz + (j-1)*newNz + k])
          /A[((i-1)*nynz + (j-1)*newNz + (k-1))*spN + ifi+offA];}}}

1 个答案:

答案 0 :(得分:4)

假设您没有竞争条件,可以尝试融合循环。融合将提供更大的并行化块,这将有助于减少错误共享的影响,并可能更好地分配负载。

对于像这样的三重循环

for(int i2=0; i2<x; i2++) {
    for(int j2=0; j2<y; j2++) {
        for(int k2=0; k2<z; k2++) {
            //
        }
    }
}

你可以像这样融合

#pragma omp parallel for
for(int n=0; n<(x*y*z); n++) {
    int i2 = n/(y*z);
    int j2 = (n%(y*z))/z;
    int k2 = (n%(y*z))%z;
    //
}

在你的情况下,你可以这样做

int i, j, k, n;
int x = newNx%2 ? newNx/2+1 : newNx/2;
int y = newNy;
int z = newNz;

#pragma omp parallel for private(i, j, k)
for(n=0; n<(x*y*z); n++) {
    i = 2*(n/(y*z)) + 1;
    j = (n%(y*z))/z + 1;
    k = (n%(y*z))%z + 1;
    // rest of code
}

如果这样可以成功加快您的代码速度,那么您可以感觉很好,您可以更快地编写代码,同时进一步模糊代码。