Arrays Fortran OpenMP将在何处分配阵列

Arrays Fortran OpenMP将在何处分配阵列,arrays,stack,heap,fortran,openmp,Arrays,Stack,Heap,Fortran,Openmp,我有一个关于Fortran OpenMP和可分配阵列的问题。很简单:空间将分配到哪里?如果我有 !$omp parallel default(shared) private(arr) !$omp critical allocate( arr(BIGNUMBER) ) !$omp end critical !do calculations with many arr accesses !$omp critical deallocate( arr ) !$omp end critical

我有一个关于Fortran OpenMP和可分配阵列的问题。很简单:空间将分配到哪里?如果我有

!$omp parallel default(shared) private(arr)
!$omp critical
  allocate( arr(BIGNUMBER) )
!$omp end critical

!do calculations with many arr accesses

!$omp critical
  deallocate( arr )
!$omp end critical
!$omp end parallel
是在堆栈上还是在堆上分配空间?如果它在堆上,上面的代码和类似的代码之间有什么区别吗

allocate( arr(BIGNUMBER, nThread) )
!$omp parallel default(shared) private(localArr)
  iThread = omp_get_thread_num()

  localArr => arr(:, iThread)

  !do calculations with many localArr accesses
!$omp end parallel

deallocate( arr )
在第一个代码中,有两个关键区域。我认为,他们会降低执行速度,并且不会很好地扩展。实际上,我不确定是否可以将它们省略,因为分配是线程保存?但是,如果阵列是在堆栈上分配的,那么它应该更快,因为访问速度更快。 在第二段代码中,我肯定会将数组放在堆上,这会降低访问速度。但是如果第一个代码中的数组也在堆上分配,那么我将保存关键区域+这只是一个分配/取消分配。应该快一点吗? 在这个游戏中,阵型的大小是否有影响? 如果要在堆上分配,有没有办法强制在堆栈上分配?
简短的问题基本上是:对于这个问题,哪一个似乎是最佳的解决方案?

带有OpenMP的Fortran编译器倾向于分配自动变量,包括堆栈上的数组。当您执行显式分配时,它们将在堆上分配,但请注意,Fortran标准根本没有提到堆栈或堆,这取决于编译器。在例1中,我将省略关键部分,因为您正在分配私有变量。关于大小,由于自动数组太大,有时会出现堆栈溢出,但这可能不是您的情况。我不知道什么是最快的方法

这个程序在我的编译器中的堆上分配数组

integer,parameter :: BIGNUMBER = 100000000
real,dimension(:),allocatable :: arr

!$omp parallel default(shared) private(Arr)
allocate( arr(BIGNUMBER) )
  iThread = omp_get_thread_num()

  arr = 5

  print *, arr

deallocate( arr )
!$omp end parallel


end
这个在堆栈上,然后它崩溃了

integer,parameter :: BIGNUMBER = 100000000
real arr(BIGNUMBER)

!$omp parallel default(shared) private(Arr)
  iThread = omp_get_thread_num()

  arr = 5

  print *, arr

!$omp end parallel


end

带有OpenMP的Fortran编译器倾向于分配自动变量,包括堆栈上的数组。当您执行显式分配时,它们将在堆上分配,但请注意,Fortran标准根本没有提到堆栈或堆,这取决于编译器。在例1中,我将省略关键部分,因为您正在分配私有变量。关于大小,由于自动数组太大,有时会出现堆栈溢出,但这可能不是您的情况。我不知道什么是最快的方法

这个程序在我的编译器中的堆上分配数组

integer,parameter :: BIGNUMBER = 100000000
real,dimension(:),allocatable :: arr

!$omp parallel default(shared) private(Arr)
allocate( arr(BIGNUMBER) )
  iThread = omp_get_thread_num()

  arr = 5

  print *, arr

deallocate( arr )
!$omp end parallel


end
这个在堆栈上,然后它崩溃了

integer,parameter :: BIGNUMBER = 100000000
real arr(BIGNUMBER)

!$omp parallel default(shared) private(Arr)
  iThread = omp_get_thread_num()

  arr = 5

  print *, arr

!$omp end parallel


end

好的,弗拉基米尔说了我在标准中没有提到的大部分内容,这完全取决于实现,为什么你要使用Critical来保护你的隐私


但是。。。您给人的印象是,您认为访问堆栈上分配的内存要比访问堆上分配的内存快。在任何典型的实现中,情况并非如此——访问时间是相同的。堆栈上的内存分配通常比堆上的快,但是一旦分配了内存,访问它的时间就相同了。因此,我会减少关键因素,走第一条路——这很简单,保持私有是好的,指针是坏的,如果内存分配时间是你的限制步骤,那么你几乎肯定没有足够的工作在并行区域使并行化变得有价值。

好,Vladimir说,标准中没有提到的大部分内容,完全取决于实施情况,为什么要使用Critical来保护您的隐私


但是。。。您给人的印象是,您认为访问堆栈上分配的内存要比访问堆上分配的内存快。在任何典型的实现中,情况并非如此——访问时间是相同的。堆栈上的内存分配通常比堆上的快,但是一旦分配了内存,访问它的时间就相同了。因此,我会减少关键因素,走路线1——这更简单,保持私有是好的,指针是坏的,如果内存分配时间是你的限制步骤,那么你几乎肯定没有在并行区域得到足够的工作,使并行化变得有价值。

我确实在这个假设下,堆栈上的内存访问速度比堆上的更快。我现在是否将此与共享/私有混淆了?对共享阵列的访问速度较慢,我认为这意味着它位于堆上,而对私有阵列的访问速度较快。我完全有可能在这里得到了一些东西。还应该补充一点,分配时间不是问题,这只是对这个大数组的大量访问,所以我希望它尽可能快。我确实是在这样的假设下,堆栈上的内存访问速度比堆上的更快。我现在是否将此与共享/私有混淆了?对共享阵列的访问速度较慢,我认为这意味着它位于堆上,而对私有阵列的访问速度较快。我完全有可能在这里得到了一些东西。还应该补充一点,分配时间不是问题,只是对这个大阵列的访问量很大,所以我
我希望这尽快。好的,谢谢你的解释。我不确定临界值,因为它是同步的。在临界区域之后是一个$omp do,我不确定这一开始是否意味着在do循环开始之前需要分配阵列。我想我是在走拯救路线。但分配时间本身实际上应该不是什么大问题,但我将尝试放弃关键问题,看看会发生什么:thx.OpenMP将始终在堆栈上分配。防止这种情况发生的唯一方法是手动在并行块内分配数组,就像OP在第一个示例中所做的那样。好的,谢谢您的解释。我不确定临界值,因为它是同步的。在临界区域之后是一个$omp do,我不确定这一开始是否意味着在do循环开始之前需要分配阵列。我想我是在走拯救路线。但分配时间本身实际上应该不是什么大问题,但我将尝试放弃关键问题,看看会发生什么:thx.OpenMP将始终在堆栈上分配。防止这种情况的唯一方法是手动在并行块内分配数组,就像第一个示例中的OP那样。。。但这意味着arr在线程之间共享。我想你不想那样。指针localArr将为每个线程提供一个副本,但指向的内容将被共享。一个线程对数组内容的更改将反映在其他线程中。。。但这意味着arr在线程之间共享。我想你不想那样。指针localArr将为每个线程提供一个副本,但指向的内容将被共享。一个线程对数组内容的更改将反映在其他线程中。