1

我有几个关于在 Fortran 并行编程中使用公共块的问题。

  1. 我的子程序有共同的块。我是否必须在并行执行区域中声明所有公共块和线程私有?

  2. 他们如何传递信息?我想为每个线程单独的公共时钟,并希望它们通过并行区域的末端传递信息。它发生在这里吗?

  3. 我的Ford子例程更改了公共块中的一些变量,并且Condact子例程再次覆盖它们,但该函数使用来自Condact子例程的值。第二个子例程和函数是否从每个线程的前一个子例程中复制变量?

    program
    ...
    ! Loop which I want to parallelize
    !$OMP parallel DO
    !do I need to declear all common block and threadprivate them here?
    I = 1, N
    ...
    call FORD(i,j)
    ...
    !$OMP END parallel DO
    end program
    
    subroutine FORD(i,j)
    dimension zl(3),zg(3)
    common /ellip/ b1,c1,f1,g1,h1,d1,
    .               b2,c2,f2,g2,h2,p2,q2,r2,d2
    common /root/ root1,root2
    !$OMP threadprivate (/ellip/,/root/)
    !this subroutine rewrite values of b1, c1 and f1 variable.
    CALL CONDACT(genflg,lapflg)
    return
    end subroutine
    
    SUBROUTINE CONDACT(genflg,lapflg)
    common /ellip/ b1,c1,f1,g1,h1,d1,b2,c2,f2,g2,h2,p2,q2,r2,d2
    !$OMP threadprivate (/ellip/)
    ! this subroutine rewrite b1, c1 and f1 again
    call function f(x)
    RETURN
    END
    
    function f(x)
    common /ellip/ b1,c1,f1,g1,h1,d1,
    .               b2,c2,f2,g2,h2,p2,q2,r2,d2
    !$OMP threadprivate (/ellip/)
    ! here the function uses the value of b1, c1, f1 from CONDAT subroutine.
    end
    
4

2 回答 2

1

首先,正如上面的评论所说,我强烈建议不要common在现代代码中使用,并且混合全局数据和并行性只是要求一个痛苦的世界——事实上,全局数据只是一个坏主意。

好的,你的问题:

  1. 我的子程序有共同的块。我是否必须在并行执行区域中声明所有公共块和线程私有?

不,threadprivate是一个声明性指令,只能在代码的声明性部分中使用,并且必须出现在每个声明之后。

  1. 他们如何传递信息?我想为每个线程单独的公共时钟,并希望它们通过并行区域的末端传递信息。它发生在这里吗?

正如您怀疑每个线程都会获得自己的common块版本。当您进入第一个并行区域时,块中的值将是未定义的,除非您用于copyin广播来自主线程的值。对于后续并行区域,只要每个区域中使用的线程数相同,就会保留这些值。在区域之间,公共块中的值将是主线程的值。

  1. 这些公共块是否可以通过子程序访问?我的 Ford 子例程重写了公共块中的一些变量,Condat 子例程再次重写了它们,但该函数使用来自 Condat 子例程的值。是否可以在这里使用 threadprivate 重写和传递公共块变量?

我不得不承认我不确定你在这里问什么。但是如果你问是否可以使用 common 来在 OpenMP 代码中的不同子程序之间传递变量,答案是肯定的,就像在串行 Fortran 中一样(注意大写)

于 2015-09-08T09:56:37.463 回答
0

将通用块转换为模块怎么样?

更改common /root/ root1, root2use gammax,然后创建一个新文件root.f,其中包含:

module root
implicit none
save
real :: root1, root2
!$omp threadprivate( root1, root2 )
end module root
于 2017-04-27T21:29:06.683 回答