自几年前我完全不懂Fortran开始,我过度使用了没有参数的
我想象中这两种方法可能会有性能上的差异,我想了解一下。在下面的MWE中,我编写了3个过程来执行相同的计算,但我不知道应该选择哪一个;我也不知道是否有其他更好的方法。
需要注意的是,我的程序中所有的三维实际数组都是可分配的,并且必须是这样的。
SUBROUTINE
,以及共享数据,因此这些程序已经对通过USE
语句可用的实际参数进行了计算。现在我需要重用其中一些过程(考虑计算体积中的散度,一个DIMENSION(:,:,:)
大的数组,从该体积中的矢量场,3个DIMENSION(:,:,:)
大的数组粘合在一起的派生类型),我希望要么保持它们是SUBROUTINE
但删除USE
语句并使用IN
/OUT
/INOUT
虚拟参数(容易),要么将它们转换为FUNCTION
(稍微困难一些,因为我需要学习一下)。我想象中这两种方法可能会有性能上的差异,我想了解一下。在下面的MWE中,我编写了3个过程来执行相同的计算,但我不知道应该选择哪一个;我也不知道是否有其他更好的方法。
需要注意的是,我的程序中所有的三维实际数组都是可分配的,并且必须是这样的。
PROGRAM mymod
IMPLICIT NONE
TYPE blk3d
REAL, DIMENSION(:,:,:), ALLOCATABLE :: values
END TYPE blk3d
TYPE(blk3d) :: A, B
INTEGER, PARAMETER :: n = 2
INTEGER :: i
ALLOCATE(A%values(n,n,n))
A%values = RESHAPE([(i/2.0, i = 1, PRODUCT(SHAPE(A%values)))], SHAPE(A%values))
print *, A%values
! 1st way
B = myfun(A)
print *, B%values
DEALLOCATE(B%values)
! 2nd way
ALLOCATE(B%values(n,n,n))
CALL mysub(A, B)
print *, B%values
DEALLOCATE(B%values)
! 3rd way
ALLOCATE(B%values(n,n,n))
CALL mysub2(A, B%values)
print *, B%values
CONTAINS
FUNCTION myfun(Adummy) RESULT(Bdummy)
IMPLICIT NONE
TYPE(blk3d), INTENT(IN) :: Adummy
TYPE(blk3d) :: Bdummy
ALLOCATE(Bdummy%values, mold = Adummy%values)
Bdummy%values(:,:,:) = 2*Adummy%values
END FUNCTION myfun
SUBROUTINE mysub(Adummy, Bdummy)
IMPLICIT NONE
TYPE(blk3d), INTENT(IN) :: Adummy
TYPE(blk3d), INTENT(INOUT) :: Bdummy
Bdummy%values(:,:,:) = 2*Adummy%values
END SUBROUTINE mysub
SUBROUTINE mysub2(Adummy, Bdummy)
IMPLICIT NONE
TYPE(blk3d), INTENT(IN) :: Adummy
REAL, DIMENSION(:,:,:), INTENT(OUT) :: Bdummy
Bdummy(:,:,:) = 2*Adummy%values
END SUBROUTINE mysub2
END PROGRAM mymod
编辑
在我的CFD程序中,我使用了几个三维大数组。这些数组相互作用,即对某些数组进行计算(不仅仅是点对点的+
/-
/*
),以获得其他数组。考虑通过示例中的四种方法之一基于A
计算出B
,然后使用A = A + B
来升级A
本身的情况。如果我选择函数方法,那么我是否错误地认为上述4个选项可以完成相同的任务?在这个意义上,我可以简单地调用A = A + myfun(A)
。
编辑2
实际派生类型,以及那个大的三维数组,有半打其他字段(标量和小静态数组);此外,该类型的大多数变量都是数组,例如TYPE(blk3d),DIMENSION(n) :: A
。
INOUT
替换OUT
以处理在过程外分配的数组?回答你的问题:不,这些差异对我来说并不清楚。我想做的显然更清楚,但是你的反对意见可以帮助我更深入地了解问题,并引导我重新思考问题。 - Enlicoelemental
而非复制整个数组进行处理。 - John AlexiouA
和B
之间的实际关系远远超过了B = 2*A
这个简单的代码行。 - Enlico