gpt4 book ai didi

fortran - 使用 OpenMP 关键和有序

转载 作者:行者123 更新时间:2023-12-02 00:01:38 25 4
gpt4 key购买 nike

我对 Fortran 和 OpenMP 很陌生,但我正在努力了解自己的方向。我有一段代码用于计算我试图并行化的变异函数。但是,我似乎遇到了竞争条件,因为有些结果相差了千分之一左右。

问题似乎是减少。使用 OpenMP 缩减工作并给出正确的结果,但它们是不可取的,因为缩减实际上发生在另一个子程序中(我将相关行复制到 OpenMP 循环中进行测试)。因此,我将减少内容放在 CRITICAL 部分,但没有成功。有趣的是,这个问题只发生在实数上,而不是整数上。我已经考虑过添加的顺序是否有任何区别,但它们不应该产生这么大的错误。

只是为了检查,我将并行中的所有内容都放在 ORDERED 块中,这(当然)给出了正确的结果(尽管没有任何加速)。我也尝试将所有内容都放在 CRITICAL 部分,但由于某种原因没有给出正确的结果。我的理解是 OpenMP 将在进入/退出 CRITICAL 部分时刷新共享变量,因此不应该有任何缓存问题。

所以我的问题是:为什么在这种情况下临界区不起作用?

我的代码如下。除了 np、tm、hm、gam 之外的所有共享变量都是只读的。

编辑:我试图通过用相同范围内的随机整数替换 do 循环来模拟由多个线程引起的随机性(即在循环中生成一对 i,j;如果它们被“访问”,则生成新的)和令我惊讶的是结果匹配。然而,经过进一步检查,发现我忘记了RNG的种子,结果巧合的是正确的。多么尴尬!

TL;DR:结果的差异是由浮点值的排序引起的。使用 double 反而会有所帮助。

!$OMP PARALLEL DEFAULT(none) SHARED(nd, x, y, z, nzlag, nylag, nxlag, &
!$OMP& dzlag, dylag, dxlag, nvarg, ivhead, ivtail, ivtype, vr, tmin, tmax, np, tm, hm, gam) num_threads(512)
!$OMP DO PRIVATE(i,j,zdis,ydis,xdis,izl,iyl,ixl,indx,vrh,vrt,vrhpr,vrtpr,variogram_type) !reduction(+:np, tm, hm, gam)
DO i=1,nd
!$OMP CRITICAL (main)
! Second loop over the data:
DO j=1,nd

! The lag:
zdis = z(j) - z(i)
IF(zdis >= 0.0) THEN
izl = INT( zdis/dzlag+0.5)
ELSE
izl = -INT(-zdis/dzlag+0.5)
END IF
! ---- SNIP ----

! Loop over all variograms for this lag:

DO cur_variogram=1,nvarg
variogram_type = ivtype(cur_variogram)

! Get the head and tail values:

indx = i+(ivhead(cur_variogram)-1)*maxdim
vrh = vr(indx)
indx = j+(ivtail(cur_variogram)-1)*maxdim
vrt = vr(indx)
IF(vrh < tmin.OR.vrh >= tmax.OR. vrt < tmin.OR.vrt >= tmax) CYCLE

! ----- PROBLEM AREA -------
np(ixl,iyl,izl,1) = np(ixl,iyl,izl,1) + 1. ! <-- This never fails
tm(ixl,iyl,izl,1) = tm(ixl,iyl,izl,1) + vrt
hm(ixl,iyl,izl,1) = hm(ixl,iyl,izl,1) + vrh
gam(ixl,iyl,izl,1) = gam(ixl,iyl,izl,1) + ((vrh-vrt)*(vrh-vrt))
! ----- END OF PROBLEM AREA -----

!CALL updtvarg(ixl,iyl,izl,cur_variogram,variogram_type,vrt,vrh,vrtpr,vrhpr)
END DO
END DO
!$OMP END CRITICAL (main)
END DO
!$OMP END DO
!$OMP END PARALLEL

首先十分感谢!

最佳答案

如果您使用 32 位浮点数和算术运算,84.26539 之间的差异和 84.26538 ,即1的差异在最低有效位中,完全可以由并行浮点运算的非确定性来解释。请记住,一个 32 位的 f-p 数字只有大约 7 个十进制数字可供使用。

普通的浮点运算不是严格结合的。对于实数(在数学上不是 Fortran 意义上的)数字 (a+b)+c==a+(b+c)但浮点数没有这样的规则。这在 Wikipedia article on floating-point arithmetic 中有很好的解释。 .

出现不确定性的原因是,在使用 OpenMP 时,您将操作顺序的控制权交给了运行时。跨线程的值的总和(例如对 + 的减少)将全局总和表达式的括号留给运行时。同一个 OpenMP 程序的 2 次执行甚至不一定会产生与最后一位相同的结果。

我怀疑即使在一个线程上运行 OpenMP 程序也可能与等效的非 OpenMP 程序产生不同的结果。由于对 OpenMP 可执行文件可用线程数的了解可能会推迟到运行时,因此无论最终是否并行运行,编译器都必须创建并行化的可执行文件。

关于fortran - 使用 OpenMP 关键和有序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20993327/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com