我是一名OpenMP新手,我遇到了问题!我有一个循环求和的数组,但我遇到了并行化问题。你能建议怎么做吗?主循环概述如下:
REAL A (N) ! N is an integer
!$OMP PARALLEL
DO I=1,10 ! just an illustration
DO J=1,10 ! can't post real code sorry, illegal
!$OMP DO
DO K=1,100
call messy_subroutine_that_sums_A(I,J, K, A) ! each thread returns its own sum
! each thread returns its own A right? and needs to summed quickly
END DO
!$OMP END DO
END DO
END DO
SUBROUTINE messy_subroutine_that_sums_A(I,J, K, A)
REAL A(N) ! an array
! basically adds some stuff to the previous value of A
A=A+junk ! this is really junk
END SUBROUTINE messy_subroutine_that_sums_A
我的问题是我从所有线程收集A
的所有尝试都失败了。如果您注意到A
也会在外循环上求和。从所有数组中收集A
作为总和的正确和快速程序是什么。其次,我的问题不仅仅是Fortran问题,它同样适用于C和C ++。这是一个概念性问题。
答案 0 :(得分:0)
实际上,OpenMP支持减少C,C ++(最近在OpenMP 4.1评论草案版本中声明)中的数组,以及Fortran中的原因。
并非所有实现都支持此功能,因此您最好首先检查编译器是否支持它。要查看您是否有正确的计算,您可以将A=A+junk
放入关键部分:
!$omp critical
A=A+junk
!$omp end critical
这应该在OMP DO循环后的所有线程中给出相同的正确答案。
然后你可以在OMP DO循环中使用数组缩减而不是critical
来优化性能,在循环之后的所有线程中再次具有相同的正确答案。
然后你可以进一步优化性能将还原转移到OMP PARALLEL,但是在这种情况下你将无法检查所有线程中的值,因为所有线程都可以使用数组A的私有副本,因此具有不同的部分值。在OMP PARALLEL之后,最终的正确答案将仅在主线程中可用。
注意,您不需要在Fortran中声明循环迭代变量是私有的,因为它们应该自动变为私有。