考虑以下最小工作示例:
module lib
type FG_t
real,allocatable::g(:)
contains
procedure,private::FG_Assign
generic::assignment(=)=>FG_Assign
end type
interface operator(-)
procedure FG_Sub
end interface
contains
elemental subroutine FG_Assign(this,that)
class(FG_t),intent(inout)::this
class(FG_t),intent(in)::that
this%g=that%g
end
elemental type(FG_t) function FG_Sub(this,that)
class(FG_t),intent(in)::this
real,intent(in)::that
FG_Sub=FG_t(this%g-that)
end
end
program prog
use lib
type(FG_t)::arr(1000),arr_(SIZE(arr))
do i=1,SIZE(arr)
allocate(arr(i)%g(10))
end do
do i=1,100000
arr_=arr-1.
end do
end
运行使用 ifx (2022.2.1)、ifort (2021.7.1)、nvfortran (22.9) 或 nagfor (7.1) 的代码生成的可执行文件时,内存会快速填满(这可能导致您的 PC 在以下情况下崩溃)更高的迭代次数)。记忆与时间:
使用 gfortran (11.1.0) 或将
elemental
之前的 FG_assign
替换为 pure
解决了我的英特尔编译器版本的问题(但不适用于 Nvidia 和 NAG 编译器)。但是,elemental
关键字在 Fortran stdlib 代码中的类似上下文中用于赋值。
Intel VTune Profiler 显示在
this%g=that%g
行调用FG_Sub
后,大部分内存分配在arr_=arr-1.
行。
这个依赖于编译器的问题是什么原因,有没有办法避免?
这似乎是一个编译器错误。 Intel、Nvidia 和 NAG 对此问题做出了回应并提交了错误报告。他们的 ID 是 CMPLRLLVM-44748(Intel)和 TPR #33180(Nvidia)。
可以通过删除
elemental
之前的FG_Assign
关键字或迭代数组元素(这样就不会使用FG_Assign
的元素属性)来避免这个问题。对于第二个解决方案arr_=arr-1.
应该替换为
do k=1,SIZE(arr)
arr_(k)=arr(k)-1.
end do