我想计算一个二维浮点阵列' Image2D'并使用' OpenMP '更快地完成此操作在并行中执行外部for循环。
在循环中,位置' [jy] [jx]'在里面' Image2D'得到计算。因此,有可能在同一时刻,两个(或更多)线程想要增加' Image2D'在相同位置' [jy] [jx]'。在我理解的内容中(但你可以纠正我)在这种情况下只执行一个增量而另一个增量丢失。
为避免这种情况,我想添加一行代码' #pragma omp critical'。它确保只有一个线程可以读取/增加/写入变量' Image2D'。
不幸的是,这意味着当第一个线程正在访问' Image2D'时,其他线程必须等待,直到第一个线程完成其工作。对于我的代码,这将极大地减慢执行,因为' Image2D'随时访问。
此外' #pragma omp critical'是太严格:它会阻止多个线程访问整个数组' Image2D'虽然足以阻止访问一个元素的Image2D' (即一个位置' Image2D [jy] [jx]')。
所以,我的问题是:有办法吗? (i)防止多个线程写入Image2D [jy] [jx]'同时; (ii)不让线程不必要地等待彼此,从而获得快速代码。
感谢您的回答
#pragma omp parallel private( ia, iR, Cte, jjx, jx,jy )
{ // start parallel
#pragma omp for
for ( ia = i0a; ia <= i1a; ia++ ) {
// ... code removed ....
for ( iR = i0R; iR <= i1R; iR++ ) {
// ... code removed ....
// 'Cte' (float) and 'jjx' (float) are computed
for ( jy = j0y; jy <= j1y; jy++ ) {
// ... code removed ...
// 'jx' (int) gets computed
#pragma omp critical
Image2D[jy][jx] += Cte * ( 1.0 - ( jjx - jx ) ); // increment 'Image2D[jy][jx]'
// ... code removed ....
} // Next 'jy'
} // Next 'iR'
}// Next 'ia'
}// end parallel section
答案 0 :(得分:0)
我不了解OpenMP,但听起来它并不能完全满足您的控制水平。
正如PetrH建议最好的答案可能是每个线程都有一个私有数组,然后再对这些数组求和。即便如此也可以并行化。
只要你有记忆,它就能很好地运作。如果不是,您可能需要考虑替代方案。这可能涉及互斥信号量。
显然,你的2D阵列足够大,需要OpenMP,因此每个单元的互斥量可能会浪费。每行可以有一个互斥锁,或者每10行一个,等等。互斥锁越少,两个线程争用同一组单元的机会就越大。此外,虽然您将在每次循环迭代时使用并提供互斥锁(并计算哪个互斥锁),但现在操作系统需要付出很多努力来快速进行互斥信号量系统调用。可能每个线程有一点额外的CPU时间可以为您提供所需的调度,因此总体效益可能会很好。