使用omp减少嵌套循环

时间:2012-05-02 17:47:07

标签: c nested parallel-processing openmp

我无法并行化嵌套for循环。代码看起来像这样

  for( k = 0; k < m; k++ ) {
    for( i = 0; i < k; i++ ) {
      s = 0.0;
#pragma omp parallel for default(none) shared(i, k, q, m, n) private(j) reduction(+:s)
      for( j = 0; j < n; j++ ) {
        s += q[ i ][ j ] * q[ k ][ j ];
      }
    }
  }

此代码有效,但由于在'k'和'i'循环下多次创建和销毁线程所产生的开销,因此运行速度非常慢。

理想情况下我想要这样的东西

#pragma omp parallel default(none) shared(i, k, q, m, n, s) private(j)
  for( k = 0; k < m; k++ ) {
    for( i = 0; i < k; i++ ) {
      s = 0.0;
#pragma omp for reduction(+:s)
      for( j = 0; j < n; j++ ) {
        s += q[ i ][ j ] * q[ k ][ j ];
      }
    }
  }

并行区域仅创建一次。但是,我的结果不正确。我认为这是因为变量's'是共享的。

有没有办法分享并仍在进行减少?

谢谢!

P.S。我不能并行'k'或'i'循环,因为它们依赖于先前的迭代。

1 个答案:

答案 0 :(得分:1)

只是我或者你省略了i循环中的部分代码吗?由于该代码只计算了许多点积,但最后只有q[m-1][]q[m-2][]的点积存储在s中。同样如上所述,您的代码在循环迭代之间没有数据依赖性,但如果使用静态调度并行化另一个循环,则会更容易出现负载不平衡。您可以使用动态调度来解决这个问题:

#pragma omp parallel default(none) shared(q, m, n) \
            private(i, k, j) lastprivate(s) schedule(dynamic,1)
for( k = 0; k < m; k++ ) {
  for( i = 0; i < k; i++ ) {
    s = 0.0;
    for( j = 0; j < n; j++ ) {
      s += q[ i ][ j ] * q[ k ][ j ];
    }
  }
}

如果您的编译器支持3.0或更高版本的标准,您也可以尝试使用OpenMP任务。

@Zhenya,如果j-loop是最外层的话,那么缓存的好处将会丢失,因为q[i][j]q[i+1][j]在C / C ++的内存中不相邻。