1

我无法并行化嵌套的 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' 是共享的。

有没有办法让's'共享并仍然执行减少?

谢谢!

PS 我不能并行化“k”或“i”循环,因为它们依赖于以前的迭代。

4

1 回答 1

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 循环是最外层的,那么缓存的好处将丢失,因为在 C/C++ 中的内存q[i][j]q[i+1][j]不相邻。

于 2012-05-04T10:38:17.247 回答