【发布时间】:2018-01-23 05:51:55
【问题描述】:
我正在 Fortran 中创建点的随机分布,这是通过 do while 循环完成的。我想通过 OpenMP 加速这个过程,但我读到你不能简单地将 !$OMP PARALLEL DO 用于 do while 循环。我尝试将我原来的 do while 转换为嵌套在 do while 中的 do 循环。但是,我在代码中看不到任何加速,我的意思是它需要与串行版本相同的时间。我似乎无法弄清楚问题是什么,并且我被卡住了,不胜感激。我已经展示了下面的代码。
原来的循环:
!OMP PARALLEL DO
do while (count < size(zeta_list,2))
call random_number(x)
call random_number(y)
x1 = a + FLOOR((b+1-a)*x)
y1 = a + FLOOR((b+1-a)*y)
if (abs(y1) <= abs(1/x1)) then
count = count + 1
call random_number(theta)
zeta_list(1,count) = x1*sin(2*pi_16*theta)
zeta_list(2,count) = x1*cos(2*pi_16*theta)
end if
end do
!OMP END PARALLEL DO
在我尝试转换后,
!$OMP PARALLEL
do while (count < size(zeta_list,2))
!$OMP DO
do i=1,size(zeta_list,2),1
call random_number(x)
call random_number(y)
x1 = a + FLOOR((b+1-a)*x)
y1 = a + FLOOR((b+1-a)*y)
if (abs(y1) <= abs(1/x1)) then
call random_number(theta)
count = count + 1
zeta_list(1,i) = x1*sin(2*pi_16*theta)
zeta_list(2,i) = x1*cos(2*pi_16*theta)
end if
end do
!$OMP END DO
end do
!$OMP END PARALLEL
整个代码是
PROGRAM RANDOM_DISTRIBUTION
IMPLICIT NONE
DOUBLE PRECISION, DIMENSION(2,1000000)::zeta_list
DOUBLE PRECISION::x,y,x1,y1,theta
REAL::a,b,n
INTEGER::count,t1,t2,clock_rate,clock_max,i
DOUBLE PRECISION,PARAMETER::pi_16=4*atan(1.0_16)
call system_clock ( t1, clock_rate, clock_max )
n = 1000
b = n/2
a = -n/2
count = 0
zeta_list = 0
x = 0
y = 0
x1 = 0
y1 = 0
theta = 0
call random_seed()
!$OMP PARALLEL
do while (count < size(zeta_list,2))
!$OMP DO
do i=1,size(zeta_list,2),1
call random_number(x)
call random_number(y)
x1 = a + FLOOR((b+1-a)*x)
y1 = a + FLOOR((b+1-a)*y)
if (abs(y1) <= abs(1/x1)) then
call random_number(theta)
count = count + 1
zeta_list(1,i) = x1*sin(2*pi_16*theta)
zeta_list(2,i) = x1*cos(2*pi_16*theta)
end if
end do
!$OMP END DO
end do
!$OMP END PARALLEL
call system_clock ( t2, clock_rate, clock_max )
write ( *, * ) 'Elapsed real time = ', real ( t2 - t1 ) / real ( clock_rate) ,'seconds'
stop
END PROGRAM RANDOM_DISTRIBUTION
使用 gfortran test.f90 -fopenmp 编译
【问题讨论】:
-
你如何衡量加速比?展示实际结果。代码中未显示的部分有多大(se minimal reproducible example)?你的变量是如何声明的?
-
您使用哪些编译器?并非所有编译器都允许
random_number并行,有些编译器可能会串行生成数字,即使它们允许random_number并行。有可用的并行随机数生成器。 -
关于您的样本有很多话要说。 1. 结果将取决于
zeta_list在其第二维中的大小。如果它很小,线程的成本将使任何加速都不太可能。 2. 在不声明“线程绑定”变量的情况下使用 OpenMP 会使结果错误并且代码变慢。 3. 正如 Vladimir 所提到的,并行随机数不是显而易见的事情。 4. pi 变量上有一个看起来很无辜的_16下划线。你的“打字”计划是什么? -
这还没有答案,但简而言之:用一个更简单的例子启动 OpenMP,使用测试来检查 OpenMP 后的结果是否有效,并行记录随机数功能。这 依赖于编译器,因此您可能希望为您的代码选择一个固定的编译器或使用提供线程安全随机数生成的库。
-
我明白了,我应该检查一下线程安全的 rngs。我使用挂钟时间测量加速,其余代码非常小,让我重新编辑我的初始帖子以显示整个内容。我一直在使用 gfortran 编译,但我也有 ifort(没试过)。我尝试使用较大的 zeta_list 大小来掩盖线程成本,并且我之前使用过 openmp,只是对 do while 循环及其变量声明的逻辑感到困惑。