首页 文章

建议在Fortran中放置数组分配的做法

提问于
浏览
2

关于我们应该在何处分配阵列的建议或最佳实践是什么?

例如,如果我有一个(我的简化版本)程序,我将在主程序中分配输出变量(感兴趣的变量) . 这个主程序调用子程序 foo ,然后调用子程序 foo2 ,谁进行实际计算 . 我的问题是应该在哪里进行分配的最佳/推荐做法 .

  • 如果 foo2 进行实际计算,是否应该分配数组?

  • 如果 foo 调用 foo2foo 应该分配数组而 foo2 只进行计算吗?

  • 我应该编写一个新的函数/子程序来分配数组吗?

  • 或者最好在主程序上分配并将数组作为假定形状传递?

如果它很重要,我有一个名为global的模块,它包含主程序的派生类型,以及代码的主要参数,例如每个数组的大小( NiNj ,容差等)

program main
    use global
    implicit none

    type(myVar_) :: ans

    Ni = 10
    Nj = 20

    if (allocated(ans%P)) deallocate(ans%P)
    allocate(ans%P(1:Ni, 1:Nj))

    call foo(ans)

    print *, P
end program main

module global
    integer, parameter :: dp=kind(0.d0)

    integer :: Ni, Nj

    type myVar_
        real(dp), allocatable :: P(:,:)
    end type myVar_

end module global

subroutine foo(myVar)
    use global
    implicit none

    type(myVar_) :: myVar

    call foo2(myVar%P)

end subroutine

subroutine foo2(P)
    use global
    implicit none

    real(dp), intent(inout) :: P(:,:)

    ! do calculations for P
end subroutine foo2

什么是

1 回答

  • 2

    为了性能原因,避免在低级子程序中进行分配和功能确实是一种好的做法 . 从[1]中可以看出,简单的加法需要大约1-3个CPU周期,分配和释放对(“小”数组)可能需要200到500个CPU周期 .

    我建议你使用“工作”变量作为输入编写一个子程序,并可能在适当的位置操作(即用结果覆盖输入),例如:

    subroutine do_computation(input,output,work1,work2)
       work1 = ...
       work2 = ...
       output = ...
    end subroutine
    

    您可以创建一个包装函数,以便于分配:

    subroutine convenient_subroutine(input,output)
       allocate(work1(...),work2(...)
       call do_computation(input,output,work1,work2)
       deallocate(work1,work2)
    end subroutine
    

    当性能不重要时,可以调用 convenient_subroutine ,但是否则调用 do_computation 尝试在循环迭代之间和不同的其他子例程之间共享工作数组 .

    [1] http://ithare.com/infographics-operation-costs-in-cpu-clock-cycles/

相关问题