我有一个教科书示例,演示了通过参数修复数据范围。我想知道为什么在下面的代码片段中,作者使用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
答案 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
。