3

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:

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?

V T
  • 103
  • 7
  • Which version of the Intel Fortran compiler are you using? You are asking a number questions: why does it crash the compiler (this should be reported, in my opinion, to Intel). Why behave gfortran and Intel Fortran different: in short they are independent and have their own good and weak points. Is there an error in the code, this is asking for a code review and should, probably, be asked at https://codereview.stackexchange.com/. Or is your program compiling and gives an executable but when running the executable it crashes? – albert Feb 01 '23 at 17:26
  • @Albert The compiler does not crash, and neither does the executable. It's a memory leak (with more iterations the executable generated with ifort would eventually crash, though) – PierU Feb 01 '23 at 17:30
  • 1
    With ifort (19) I can observe the memory leak even with `pure`. And actually I can see it even without overloading the assignment operator. I would say there's a bug here... There is probably a temporary array of `FG_t` objects that is created to handle `arr-1.`, it is freed after assignment to `arr_` and I would expect the allocatable components to be freed as well, but I don't know if it's required by the standard (?) – PierU Feb 01 '23 at 17:42
  • 3
    @PierU Probably the sentence "Compiling this code with ifx or ifort leads to rapid filling of memory" should be reformulated to "When running the executable generated from the code with ifx or ifort" or something alike. – albert Feb 01 '23 at 17:44
  • The situation is compiler-dependent because the Fortran standard says nothing about this aspect of memory use. If you think the particular implementation used by a particular compiler is suboptimal then you can ask the compiler vendor to change it. – francescalus Feb 01 '23 at 17:47
  • You can read some discussion of related topics in answer to [another question](https://stackoverflow.com/q/57606191/3157076). – francescalus Feb 01 '23 at 17:51
  • The mention of std_lib is noteworthy. Does std_lib cause you problems anywhere? The authors of the library would like to hear about that (if you are not the author yourself). – Vladimir F Героям слава Feb 02 '23 at 07:39
  • @PierU, albert, thank you for your suggestions. I improved the question. – V T Feb 02 '23 at 09:38
  • If you remove all mention of "elemental" and set the elements of arr_ in a loop then the problem does not occur. As it stands, the code has the same problem with the NAG compiler. Clearly I was mistaken when I thought that all allocatable arrays were automatically deallocated when they went out of scope ... – lastchance Feb 02 '23 at 09:38
  • @VladimirFГероямслава, I have not tried this code with stdlib yet. But, I suppose, replacing `FG_t` with `string_type` from stdlib and `-` with `//` can lead to a similar problem. I will check this out later. – V T Feb 02 '23 at 09:43
  • After several tests, I tend to confirm that the likely explanation is that in `FG_sub` and on the `FG_t(this%g-that)` expression the compiler is creating a temporary array of `FG_t` objects and allocate the `%g` components. And when deallocating the temporary array behind the scene it fails/forgets deallocating the `%g` components. To me it's a compiler bug. – PierU Feb 02 '23 at 11:38
  • If it forgets to deallocate any temporaries or past instances or reallocated objects, it is definitely a bug. – Vladimir F Героям слава Feb 02 '23 at 12:21
  • It's worth noting that just because a Fortran runtime deallocates an array, that doesn't mean that the memory it once lived in has to be released to or by the operating system. Memory use can still increase even when the compiler is correctly (Fortran) deallocating. In this example (Fortran) deallocation must happen in all the obvious places. (I don't dispute that unbounded increase of memory can be considered a bug.) – francescalus Feb 02 '23 at 16:43
  • @VladimirFГероямслава, I just tested it: stdlib doesn't have this problem with string_type. Maybe because it uses realloc of character type. – V T Feb 08 '23 at 19:41
  • My colleague posted the same question on the official forum of Intel Fortran Compiler ([link](https://community.intel.com/t5/Intel-Fortran-Compiler/Memory-leak-in-the-assignment-subroutine-using-ifx-and-ifort/m-p/1452646#M164819)), and a bug report has been filed (CMPLRLLVM-44748). – V T Feb 11 '23 at 12:56

1 Answers1

0

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
V T
  • 103
  • 7