在 Fortran 中创建一次然后频繁访问大型数组的最佳方式

问题描述 投票:0回答:1

我用 Fortran 进行了科学模拟。在其中,我需要在开头“一次”计算一个大数组(例如 10^5 个元素,大小已知/可以在编写代码时预设),然后需要共享/访问/读取该数组进入很多次(基本上每一步,所以可能数百万次)。

与其他子例程共享此类数组的推荐方式是什么?鉴于我希望创建大数组的代码成为它自己的实体。

假设存在情况 1,其中:

  • 该数组需要在运行时生成,实际上每次运行蒙特卡洛都会生成一次(因此在模拟过程中实际上会生成多次)。数组的大小可以认为是固定的并且是在编写代码时已知/预设的。
  • 一些不同的子例程需要在每个时间步访问数组(例如每次运行约 10^6 个时间步)
  • 他们每个人一次只能读取一个元素
  • 他们每个人都会几乎按顺序阅读(并且几乎在相同的点)

有情况 2,其中:

  • 该数组需要在运行时生成,实际上只会生成一次(对于蒙特卡罗的所有运行都是相同的)
  • 数组实际上会明显更小。数组的大小可以认为是固定的并且是在编写代码时已知/预设的。
  • 它只会在一个子例程中使用,但几乎每次都需要完全读取(即在每个时间步)。

最后是情况 3,与情况 2 完全相同,只是数组可以作为数据语句在代码中进行物理预设/写入。

每种情况下的最佳实践是什么,以及优化速度/最小化可能的运行时间损失?

编辑:这是我目前的解决方案。有一个如下形式的模块

    module big_array
    parameter (nbigarray=10**5)
    
    real my_by_array(nbigarray)
    
    contains
    
      subroutine init_big_array(arglist)
    
      *[here some code populating / creating *my_big_array*]*

      return
      end
    
    end module

在程序开始时运行

init_big_array
一次,并在需要
my_big_array
的地方使用该模块。

fortran
1个回答
0
投票

这是动态内存管理的介绍,它允许将

array
暴露给子程序。

module foo

   implicit none  ! Always include this statement
   !
   ! Make everything private and only expose those entities
   ! that are needed.
   !
   private
   public array, init_array, destroy_array

   integer, allocatable :: array(:)

   contains
      !
      ! Destroy array
      !
      subroutine destroy_array
         if (allocated(array)) then
            deallocate(array)
         end if   
      end subroutine

      subroutine init_array(n)
         integer, intent(in) :: n
         if (n < 0) then
            !
            ! Could implement a fallback.  Perhaps,
            ! allocate a zero-sized array.
            !
            write(*,'(A)') 'init_array: memory allocation issue'
            stop
         end if
         !
         ! Check if array is allocated and the requested size
         ! differs from the current allocated size.
         !
         if (allocated(array)) then
            if (size(array) /= n) then
               call destroy_array
               allocate(array(n))
            end if
         else
            allocate(array(n))
         end if   
      end subroutine
end module foo

program main
   use foo, only : array, init_array
   implicit none
   integer m
   !
   ! Perhaps, "read(*,*) m" to allow user to size
   ! memory appropriately.
   !
   m = 100

   call init_array(m)
   call bar
end program

subroutine bar
   use foo, only : array
   implicit none
   if (allocated(array) then
      print *, size(array)
   else
      write(*,'(A)') 'whoops'
   end if
end subroutine bar

© www.soinside.com 2019 - 2024. All rights reserved.