使用OpenMP进行并行化时的性能问题

时间:2017-06-02 13:39:25

标签: fortran openmp intel-fortran

我试图并行化代码,但它只会降低性能。我写了一个Fortran代码,它运行几个蒙特卡罗集成,然后找到它们的意思。

      implicit none  
      integer, parameter :: n=100
      integer, parameter :: m=1000000
      real, parameter :: pi=3.141592654

      real MC,integ,x,y
      integer tid,OMP_GET_THREAD_NUM,i,j,init,inside  
      read*,init
      call OMP_SET_NUM_THREADS(init)
      call random_seed()
!$OMP PARALLEL DO PRIVATE(J,X,Y,INSIDE,MC) 
!$OMP& REDUCTION(+:INTEG)
      do i=1,n
         inside=0
         do j=1,m
           call random_number(x)
           call random_number(y)

           x=x*pi
           y=y*2.0

           if(y.le.x*sin(x))then
             inside=inside+1
           endif

         enddo

         MC=inside*2*pi/m
         integ=integ+MC/n
      enddo
!$OMP END PARALLEL DO

      print*, integ
      end

随着线程数量的增加,运行时间急剧增加。我已经为这些问题寻找解决方案,并且在大多数情况下共享内存元素恰好是问题,但我看不出它是如何影响我的情况的。

我在使用英特尔Fortran编译器的16核处理器上运行它。

编辑:添加implicit none后的程序,声明所有变量并添加私有子句

1 个答案:

答案 0 :(得分:0)

您不应该使用RANDOM_NUMBER进行高性能计算,也不应该使用并行线程。无保证随机数发生器的质量和标准随机数发生器的线程安全性。见Can Random Number Generator of Fortran 90 be trusted for Monte Carlo Integration?

有些编译器会使用无法并行调用的快速算法。有些编译器会使用慢速方法,但可以从并行调用。有些将是快速的并且允许并行。有些会产生质量差的随机序列,有些会更好。

您应该使用一些并行的PRNG库。有许多。请参阅此处以获取有关英特尔https://software.intel.com/en-us/forums/intel-math-kernel-library/topic/283349的建议我在我自己稍微改进的版本http://www.cmiss.org/openCMISS/wiki/RandomNumberGenerationWithOpenMP中使用基于https://bitbucket.org/LadaF/elmm/src/e732cb9bee3352877d09ae7f6b6722157a819f2c/src/simplevtk.f90?at=master&fileviewer=file-view-default的库但请注意,我并不关心序列的质量我的申请,只涉及速度。

旧版本:

那里你有竞争条件。

使用

 inside=inside+1

更多线程可以竞争写入和读取变量。您将不得不以某种方式同步访问。如果你成功reduction,你将遇到问题

integ=integ+MC/n

如果您将其设为私有,那么inside=inside+1将仅在本地计算。

MC似乎也处于竞争状态,因为更多的线程将在其中写入。根本不清楚MC做了什么,为什么会这样做,因为你没有在任何地方使用这个值。 您确定所显示的代码是否完整?如果没有,请参阅如何制作Minimal, Complete, and Verifiable example

请参阅此With OpenMP parallelized nested loops run slow许多其他示例,了解竞争条件如何使程序变慢。