我试图并行化代码,但它只会降低性能。我写了一个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
后的程序,声明所有变量并添加私有子句
答案 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许多其他示例,了解竞争条件如何使程序变慢。