我在使用 Fortran 时遇到以下情况 optional 属性
对于假定的形状数组并试图找出最佳(在性能方面)解决方案。
如果有人能给我一个好的提示,我会很高兴。
请注意,我对我可以获得的每一个性能提升都很感兴趣,因为我的数组很大,循环的数量和周期甚至更大。
我的情况是,计算是使用 optional 参数完成的,或者如果它不存在,它会在其位置使用另一个数组。
subroutine compute(tmat,av,av2)
implicit none
complex,intent(out) :: tmat(:)
complex,intent(in) :: av(:)
complex,intent(in),optional :: av2(:)
if(present(av2)) then
tmat = av *av2
else
tmat = av *av
end if
end subroutine compute_transition_matrices_bosonic
在这个简单的例子中,上面的解决方案就可以了。然而,我真正的代码要复杂得多。
这意味着例程的内部块可能非常大(数百行),最重要的是包含许多嵌套循环。
人们可以想象它是这样的:
if(present(av2)) then
tmat = "function"(av,av2)
else
tmat = "function"(av,av)
end if
其中“函数”代表许多操作和循环(因此是“”)。关键是对于这两种情况,这些操作是相同的
if 语句使我需要编写两次代码。另一种解决方案是检查是否
av2
出现在使用位置代码会产生一些开销,因为此检查将非常(非常)频繁地进行。
我想知道是否有更聪明的解决方案来解决这样的问题。首先,人们可能会想到使用临时变量
complex, :: phi_tmp(:)
if(present(av2)) then
phi_tmp = av2
else
phi_tmp = av
end if
tmat = "function"(av,phi_tmp)
这通常在使用 optional 参数时完成。但这会复制数据,在我的情况下这是一个非常大的数组。
因此,我在考虑使用指针
complex,intent(in),target :: av(:)
complex,intent(in),optional,target :: av2(:)
complex,pointer :: phi_tmp(:)
if(present(av2)) then
phi_tmp => av2
else
phi_tmp => av
end if
tmat = "function"(av,phi_tmp)
但这需要
TARGET
av
的属性和 av2
.在这里我不确定这是否会导致性能下降,因为编译器不能再假设
av
和 av2
在它的优化过程中没有别名,即使这里都有 INTENT(IN)
属性这样就不会出现混叠问题。此外,如果调用例程时输入中的参数是什么意思?
没有
TARGET
属性? (这编译和工作!)有没有人对这些问题有一些经验?
有“标准”的解决方案吗? (我没找到)
最终的最佳解决方案是什么?
最佳答案
一种方法是针对当前和不存在的情况使用不同的子程序。
subroutine compute1(tmat,av)
implicit none
complex,intent(out) :: tmat(:)
complex,intent(in) :: av(:)
call compute2(tmat, av, av) ! Ensure there is an explicit interface for compute2 here
end subroutine
subroutine compute2(tmat,av,av2)
implicit none
complex,intent(out) :: tmat(:)
complex,intent(in) :: av(:)
complex,intent(in) :: av2(:)
tmat = "function"(av,av2)
end subroutine
其中两者都没有 optional 参数。
这可以添加到制作
compute
这两者的泛型。当然,这不会在所有情况下都有效,但这里使用
intent(in)
av
上的属性和 av2
在 compute2
我们不必担心混叠。
关于fortran - 如何为假定的形状数组使用 optional 属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32582929/