1

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

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

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

如果我喜欢以现代方式传递变量istartiend,我是否正确地进行了以下修订(这对我来说看起来有点奇怪,因为 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
4

1 回答 1

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

于 2014-03-18T17:12:31.450 回答