将变量直接传递给线程子例程

时间:2014-03-18 17:03:13

标签: parallel-processing fortran openmp fortran-common-block

我有一个教科书示例,演示了通过参数修复数据范围。我想知道为什么在下面的代码片段中,作者使用COMMON块来定义两个变量, istart iend,**应该是每个线程的私有?具有COMMON属性的变量的“共享”属性是否与作者将** istart iend 指定为私有的意图冲突?或者我们应该简单地删除公共块?

作者说,“我们使用一个名为bounds的公共块,其中包含istart和iend,主要包含主程序和子程序中使用的值。”我想知道公共属性是否会被每个线程的调用子例程继承,并干扰 istart iend 应该承担的“私有”属性。

program main
    ...
    common /bounds/ istart,iend
    integer :: iarray(10000),N
    N=10000
    ...
!$omp parallel private(iam,nthreads,chunk), &
!$omp& private(istart,iend)
    nthreads=omp_get_num_threads()
    iam = omp_getthread_num()
    chunk=(N+nthreads-1)/nthreads
    istart=iam*chunk+1
    iend=min((iam+1)*chunk,N)
    call work(iarray,istart,iend)
!$omp end parallel
end program main

subroutine work(iarray,istart,iend)
    ...
    integer :: iarray(10000)
    do i=istart,iend 
        iarray(i)=i*i
    endddo
end subroutine work

在另一个示例中,作者为了相同的目的编写以下代码片段。在这种情况下,我应该在主程序和子程序中保留公共块,对吧?

program main
    ...
    common /bounds/ istart, iend
!$omp threadprivate(/bounds/)
    integer iarray(10000)
    N = 10000
!$omp parallel private(iam, nthreads, chunk)
    nthreads = omp_get_num_threads()
    iam = omp_get_thread_num()
    chunk = (N + nthreads – 1)/nthreads
    istart = iam * chunk + 1
    iend = min((iam + 1) * chunk, N)
    call work(iarray)
!$omp end parallel
end program main

subroutine work(iarray)
    ...
    common /bounds/ istart, iend
!$omp threadprivate(/bounds/)
    integer iarray(10000)
    do i = istart, iend
       iarray(i) = i * i
    enddo
end subroutine work

如果我想以现代方式传递变量 istart iend ,我是否正确进行以下修订(这对我来说有点奇怪,因为threadprivate子句的参数不是公共块的名称):

program main
    use model 
    ...
!$omp threadprivate(istart,iend)
    integer iarray(10000)
    N = 10000
!$omp parallel private(iam, nthreads, chunk)
    nthreads = omp_get_num_threads()
    iam = omp_get_thread_num()
    chunk = (N + nthreads – 1)/nthreads
    istart = iam * chunk + 1
    iend = min((iam + 1) * chunk, N)
    call work(iarray)
!$omp end parallel
end program main

module model       
integer :: istart,iend
contains    
subroutine work(iarray)
    ...
!$omp threadprivate(istart,iend)
    integer iarray(10000)
    do i = istart, iend
       iarray(i) = i * i
    enddo
end subroutine work
end module model

1 个答案:

答案 0 :(得分:1)

如果这或多或少是完整的例子,我看不到公共区块的任何位置。这里没有实际的共享,因为这些值是parallel块中每个线程的私有值,它们作为伪参数传递。

我真的会删除它。

另一种情况则不同。这里使用公共块共享变量,并使用threadprivate进行私有化。这是正确的用法,虽然更现代的风格是以相同的方式使用模块变量。

我会做模块:

module parameters
  integer :: istart,iend
  !$omp threadprivate(istart,iend)
end module

module model
  use parameters
  implicit none
contains    
subroutine work(iarray)
    ...
    integer iarray(10000)
    do i = istart, iend
       iarray(i) = i * i
    enddo
end subroutine work
end module model

program main
    use parameters !not completely necessary here
    use model
    implicit none
    ...
    integer iarray(10000)
    N = 10000
!$omp parallel private(iam, nthreads, chunk)
    nthreads = omp_get_num_threads()
    iam = omp_get_thread_num()
    chunk = (N + nthreads – 1)/nthreads
    istart = iam * chunk + 1
    iend = min((iam + 1) * chunk, N)
    call work(iarray)
!$omp end parallel
end program main

请注意,threadprivate指令仅用于声明其中使用的变量。

备注,common不是变量的属性,它是包含变量的独立实体。因此,伪参数无法继承common