Parallel processing 如何在此Fortran代码中使用OpenMP正确地将lambdaeff数传递给内核?
我正在尝试并行化一个代码,该代码计算两个整数Parallel processing 如何在此Fortran代码中使用OpenMP正确地将lambdaeff数传递给内核?,parallel-processing,fortran,Parallel Processing,Fortran,我正在尝试并行化一个代码,该代码计算两个整数nue和nut;然后使用这些数字计算另一个数值lambdaeff。我可以展示一个(愚蠢的)MWE(实际代码是1200行蒙特卡罗代码): 如果我按照指示使用并行do循环并行化代码,我不确定lambdaeff编号是否会正确传递到各个内核。我如何修改循环的最后一行以正确地将lambdaeff传递到cores?总结@Vadimir F、@PetrH和@Ian Bush的评论: 不要使用rand(),因为它不是线程安全的;改用 如果要使用OpenMP 有一个大
nue
和nut
;然后使用这些数字计算另一个数值lambdaeff
。我可以展示一个(愚蠢的)MWE(实际代码是1200行蒙特卡罗代码):
如果我按照指示使用并行
do
循环并行化代码,我不确定lambdaeff
编号是否会正确传递到各个内核。我如何修改循环的最后一行以正确地将lambdaeff传递到cores?总结@Vadimir F、@PetrH和@Ian Bush的评论:
- 不要使用
,因为它不是线程安全的;改用rand()
- 如果要使用OpenMP
- 有一个大的,请查一下(后一个术语适用于这里)李>
如果我有第二个变量
lnet=lnet nue+nut
,它应该由所有线程共享,比如lambdaeff
,我应该如何修改reduce语句
您想使用OpenMP还是MPI?请澄清,它们是完全不同的东西。请在问题中包含代码。MWE将是有用的,不要使用
rand()
。当然,不要在任何并行代码中使用它,但通常也要避免使用它。对于蒙特卡罗,您需要一个可靠的经过测试的随机数生成器。对于OpenMP,您需要一些线程安全的东西。例如,在gfortran中实现的只是“g77提供的简单模生成器”,而在gfortran中实现的是使用非常好、快速的生成器和线程安全。但是,对于其他编译器,一般来说没有任何东西是可以保证的。使用专用库是很好的。请了解线程和内核之间的区别,这是您应该使用的前一个术语。但是要解决您的问题,您需要一个reduce语句-必须有一个重复的地方。如果我有第二个变量lnet=lnet nue+nut
,它应该由所有线程共享,例如lambdaeff
如何修改reduce语句?reduce语句的一般语法是:reduce(:)
,所以只需将lnet
添加到参数列表中即可。
Do n=1, 100
nue=int(100*rand())
nut=int(50*rand())
lambdaeff=lambdaeff+(nue-nut)^2
end do
program main
use, intrinsic :: omp_lib
implicit none
integer :: i, tid, nthreads
integer :: nue, nut, lambdaeff = 0, lnet = 0
real :: r(2)
! Set number of threads
nthreads = OMP_get_max_threads()
write (*,*) "Using ", nthreads, "thread(s)"
!$OMP PARALLEL NUM_THREADS(nthreads) PRIVATE(tid)
! Who am I?
tid = OMP_get_thread_num()
! Reduction do loop
!$OMP DO REDUCTION(+:lambdaeff,lnet) PRIVATE(nue,nut,r)
do i = 1, 100
call random_number(r)
nue = int(100*r(1))
nut = int(50*r(2))
lambdaeff = lambdaeff + (nue-nut)**2
lnet = lnet+(nue-nut)
end do
!$OMP END DO
! lambdaeff is same for all threads
write (*,*) tid, lambdaeff, lnet
!$OMP END PARALLEL
end program main