我无法并行化嵌套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'循环,因为它们依赖于先前的迭代。
答案 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 ++的内存中不相邻。