Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Fortran 两个openmp有序块,没有结果并行化_Fortran_Openmp - Fatal编程技术网

Fortran 两个openmp有序块,没有结果并行化

Fortran 两个openmp有序块,没有结果并行化,fortran,openmp,Fortran,Openmp,我正在写一个Fortran程序,需要有可复制的结果(用于出版)。我对以下代码的理解是,它应该是可复制的 program main implicit none real(8) :: ybest,xbest,x,y integer :: i ybest = huge(0d0) !$omp parallel do ordered private(x,y) shared(ybest,xbest) schedule(static,1) do i = 1,10 !$omp ordered

我正在写一个Fortran程序,需要有可复制的结果(用于出版)。我对以下代码的理解是,它应该是可复制的

program main
implicit none
real(8) :: ybest,xbest,x,y
integer :: i

ybest = huge(0d0)
!$omp parallel do ordered private(x,y) shared(ybest,xbest) schedule(static,1)
do i = 1,10
    !$omp ordered
    !$omp critical
    call random_number(x)
    !$omp end critical
    !$omp end ordered

    ! Do a lot of work
    call sleep(1)
    y = -1d0

    !$omp ordered
    !$omp critical
    if (y<ybest) then
    ybest = y
    xbest = x
    end if
    !$omp end critical
    !$omp end ordered
end do
!$omp end parallel do

end program
代码按如下方式运行:

real    0m10.047s
user    0m0.003s
sys 0m0.003s

real    0m10.037s
user    0m0.003s
sys 0m0.004s
但是,如果注释掉已排序的块,它将按以下时间运行:

real    0m10.044s
user    0m0.002s
sys 0m0.003s

real    0m3.021s
user    0m0.002s
sys 0m0.004s
  • 编辑-
作为对innoSPG的回应,以下是一个非平凡函数代替睡眠的结果:

real(8) function f(x)
    implicit none
    real(8), intent(in) :: x
    ! local
    real(8) :: tmp
    integer :: i
    tmp = 0d0
    do i = 1,10000000
        tmp = tmp + cos(sin(x))/real(i,8)
    end do
    f = tmp
end function


real    0m2.229s --- no openmp
real    0m2.251s --- with openmp and ordered
real    0m0.773s --- with openmp but ordered commented out

此程序不符合OpenMP标准。具体来说,问题是您有多个
有序的
区域,循环的每次迭代都将执行这两个区域。OpenMP 4.0标准有这样的表述(2.12.8,限制,第16行,第139页):

在执行循环迭代或循环区域内的循环嵌套期间,线程不得执行多个绑定到同一循环的有序区域 地区

如果有多个
有序的
区域,则必须具有条件代码路径,以便在任何循环迭代中只能执行其中一个路径



还值得注意的是,您所订购区域的位置似乎对性能有影响。使用gfortran 5.2进行测试时,在每个循环迭代中按顺序执行有序区域后,所有内容都会显示出来,因此在循环开始时使用有序块会导致串行性能,而在循环结束时使用有序块则不会产生这种影响,因为在块并行化之前的代码。使用ifort 15进行测试并没有那么引人注目,但我仍然建议您对代码进行结构化,使您的有序块出现在任何代码之后,而不是需要在循环迭代中进行并行化

如何设置线程数?你的OMP\u线程数是多少?您如何确定它不是并行运行的?性能度量的结果到底是什么样的?循环是并行运行的,这意味着100次迭代在线程之间共享。每个线程只在自己的数据上运行f,除非f中还有$omp。这就是数据的并行性。我想这就是你的意思。现在你的问题是什么?Vladmir,我使用环境变量OMP_NUM_THREADS,对于linux等于6,对于max等于4。
top
显示它以100%的速度运行,有时甚至有一点超过。innoSPG,f中有一个OMP pragma,有点像。我必须通过
声明一些模块变量私有$omp线程专用
。我不知道你所说的“数据并行性”是什么意思。我希望每个线程对不同的
x
值执行
f
。也许我还应该说,在不担心再现性的代码中(因此缺少有序结构),
top
显示大约400%或600%。非常感谢!将代码重新构造为只有一个有序部分后,使用单有序构造的时间为1.056,不使用单有序构造的时间为3.240。
real(8) function f(x)
    implicit none
    real(8), intent(in) :: x
    ! local
    real(8) :: tmp
    integer :: i
    tmp = 0d0
    do i = 1,10000000
        tmp = tmp + cos(sin(x))/real(i,8)
    end do
    f = tmp
end function


real    0m2.229s --- no openmp
real    0m2.251s --- with openmp and ordered
real    0m0.773s --- with openmp but ordered commented out