Openmp:如何从不同的线程收集数组?

时间:2015-08-13 13:36:08

标签: c++ arrays multithreading fortran openmp

我是一名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 ++。这是一个概念性问题。

1 个答案:

答案 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中声明循环迭代变量是私有的,因为它们应该自动变为私有。