Consider the following minimal working example:
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
When running the executable generated from the code with ifx (2022.2.1), ifort (2021.7.1), nvfortran (22.9), or nagfor (7.1), memory fills rapidly (which can lead to your PC crashing in the case of a higher number of iterations). Memory vs time:
Using gfortran (11.1.0) or replacing elemental
before FG_assign
with pure
fixes the problem for my version of Intel compiler (but not for the Nvidia and NAG compilers). However, the elemental
keyword is used for assignment in a similar context in the code of Fortran stdlib.
Intel VTune Profiler shows that most of the memory is allocated in the line this%g=that%g
after FG_Sub
is called in the line arr_=arr-1.
.
What is the reason for this compiler-dependent problem, and is there a way to avoid it?
It appears to be a compiler bug. Intel, Nvidia, and NAG responded and filed bug reports for this issue. Their IDs are CMPLRLLVM-44748 (Intel) and TPR #33180 (Nvidia).
This issue can be avoided by removing the elemental
keyword before FG_Assign
or by iterating over the elements of arrays (so that the elemental property of FG_Assign
won't be used). For the second solution arr_=arr-1.
should be replaced with
do k=1,SIZE(arr)
arr_(k)=arr(k)-1.
end do