Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
28439 Discussions

Memory leak in the assignment subroutine using ifx and ifort

Michel-Heinz
Beginner
1,239 Views

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 above-mentioned code with ifx (2022.2.1) or ifort (2021.7.1) the system memory fills up rapidly (which can lead to your PC crashing in the case of a higher number of iterations).

Memory vs time:

MemoryVSTime.png

Using gfortran (11.1.0) or replacing 'elemental' before 'FG_Assign' with 'pure' fixes the problem for the latest versions of ifx and ifort. Thanks to a fruitful discussion on Stack overflow (https://stackoverflow.com/questions/75313786/memory-leak-in-the-assignment-using-intel-fortran-compiler), the most probable explanation for this behavior is the creation of a temporary array of FG_t object in the line  'FG_sub=FG_t(this%g-that)'.  After use, the temporary array will be deallocated, but the '%g' components will not.

0 Kudos
1 Solution
Barbara_P_Intel
Moderator
1,055 Views

Thank you!


I filed a bug report for you, CMPLRLLVM-44748.



View solution in original post

7 Replies
Steve_Lionel
Honored Contributor III
1,197 Views

There was a bug fixed in this area in the 2023.0.0 release - please try that.

0 Kudos
Michel-Heinz
Beginner
1,187 Views

Thanks for the reply! I just compiled the code with the ifx and ifort compiler from the 2023 release, and for both compilers the problem remains the same.

0 Kudos
Barbara_P_Intel
Moderator
1,121 Views

Always good to use the latest release for bug fixes and security patches! 

@Michel-Heinz, what OS are you compiling and running on?

 

0 Kudos
Michel-Heinz
Beginner
1,096 Views

The OS used tor compiling and running is Ubuntu 22.04.1 LTS.

0 Kudos
Barbara_P_Intel
Moderator
1,056 Views

Thank you!


I filed a bug report for you, CMPLRLLVM-44748.



FortranFan
Honored Contributor II
1,039 Views

@Michel-Heinz ,

Clearly an Intel problem in this instance but please note for future reference you may want to take care your code reproducers do not allow really smart processors to optimize away the crucial instructions of interest to you in a reproducer, particularly if you are cross-checking with different compilers, some of whom can be really sharp.  You will note your loop over 100000 iterations in the original post.  A really astute processor will notice no need to run the loop at all.  

Including some dummy instructions like so to prevent the compiler from optimizing away may prove essential in other situations:

 

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%g = this%g - that !<-- No need for structure constructor
    end
end

program prog
    use lib
    integer, parameter :: N = 1000
    integer, parameter :: M = 100000
    type(FG_t)::arr(N),arr_(SIZE(arr))
    real, allocatable :: x(:)
    allocate( X(M) )
    do i = 1, SIZE(arr)
       allocate( arr(i)%g(10), source=0.0 ) ! define the component 'g' also
    end do
    do i = 1, M
       arr_ = arr - 1.0
       x(i) = sum( arr_(1)%g + arr_(N)%g )  ! dummy instructions to prevent the compiler from optimizing away
    end do
    print *, x(1), x(M) ! dummy instructions to prevent the compiler from optimizing away
end

 

 

0 Kudos
Barbara_P_Intel
Moderator
518 Views

The compiler team reports that the memory leak is fixed in the Fortran compiler that was released this week. It's part of oneAPI HPC Toolkit 2023.2.

Please install it and see how it works for you!



0 Kudos
Reply