2017-06-02 102 views
0

我试图对代码进行并行处理,但这只会降低性能。我写了一个Fortran代码,运行几个蒙特卡洛集成,然后找到他们的意思。使用OpenMP进行并行处理时的性能问题

 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

欢迎。请参加[Tour],建议所有新人参加。你是如何衡量时间的? –

+0

请参阅我如何更改代码中的缩进。将所有代码缩进以便人们可以看到结构是很好的。对你来说保留源文件也是有好处的。 –

+0

'里面'是什么?它从何而来?请确保你使用'IMPLICIT NONE'。 –

回答

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你会如果你把它私有的,那么inside=inside+1将仅在本地计算有问题

integ=integ+MC/n 

MC也似乎处于竞态条件,因为更多的线程将写入它。目前还不清楚MC做什么以及它为什么在那里,因为您没有在任何地方使用该值。 您确定您显示的代码是完整的吗?如果不是,请参阅如何制作Minimal, Complete, and Verifiable example

查看此With OpenMP parallelized nested loops run slow许多其他示例竞争条件如何使程序变慢。

+0

'inside'内,默认情况下,是一个私有变量。我希望外部循环并行运行,以便内部循环独立运行在不同的线程中。 'MC'存储集成的价值。 'MC'独立计算n次,平均值存储在'integ'中。我还尝试删除'integ',以便所有内容都是私人的,以便查看时间差异,但它对运行时间没有任何影响。 –

+0

你为什么认为这是默认的私人?你的代码中没有这样的设置。默认情况下一切都是共享的我坚信由于比赛条件,节目很慢。你比较了串行和并行代码的结果吗?他们是相同还是不同?我敢打赌他们会有所不同。 –

+0

我试着添加'DEFAULT(PRIVATE)',但它没有任何效果(这就是为什么我认为它必须是默认私人,我的坏)。令人惊讶的是,对于使用或不使用'DEFAULT(PRIVATE)'的串行和并行代码,结果都是相同的。结果也是正确的,小数点后3位。我还尝试使用'PRIVATE'子句定义所有私有变量,但这也没有帮助。 –