Parallel processing 将变量直接传递到线程化子例程中

Parallel processing 将变量直接传递到线程化子例程中,parallel-processing,fortran,openmp,fortran-common-block,Parallel Processing,Fortran,Openmp,Fortran Common Block,我有一个教科书上的例子,演示如何通过参数确定数据范围。我想知道为什么在下面的代码片段中,作者使用一个公共块来定义两个变量,istart和iend,**它们应该是每个线程的私有变量?具有公共属性的变量的“共享”属性是否与作者将**istart和iend指定为私有的意图相冲突?还是我们应该简单地删除公共块 作者说,“我们使用一个名为bounds的公共块,其中包含istart和iend,基本上包含主程序和子例程中使用的值。”我想知道每个线程的调用子例程是否会继承公共属性并干扰“private”ista

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

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

背风

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

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子句的参数不是公共块的名称):


如果这或多或少是一个完整的例子,我看不到公共块的任何位置。这里没有实际的共享,因为这些值对于
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

我有一个与此线程相关的派生问题。请再看我的帖子。谢谢。我已经扩展了答案。请看我在原始帖子底部对你建议的修改。看起来不错,只有threadprivate指令应该接近变量的定义。此外,如果更合适,变量可以在单独的模块中。那要视情况而定。谢谢。还有一个问题。你的意思是,除了主程序单元中的一个,我还需要放另一个$omp threadprivate(istart,iend)就在模块“模型”中“istart”和“iend”变量声明区域之后,而不是在本地过程——子程序“work”中?
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
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