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

Mapping memory area with set of variables

netphilou31
New Contributor II
722 Views

Dear Fortran experts,

I am currently attempting to remove commons from a legacy code in order to be able to dynamically allocate the corresponding sizes and then reduce the memory usage. I would like to know if there is a way to allocate a memory area using the malloc function and then to map several variables to this memory area. I would like to do something like:

      real(8) Array(*)
      pointer (ptr, Array)
C
      real(8) VAR1
      real(8) VAR2
      real(8) VAR3(NC,NC)
C
      ptr = malloc((NC*NC+2)*sizeof(0.D0))

Question : How to map VAR1 to Array(1), VAR2 to Array(2) and VAR3 to Array(3:2*NC*NC-1) ?

I have tried using derived type with unions and maps but this not really satisfying especially for arrays of dynamic sizes (like VAR3(NC,NC) above).

Do you think that using typed pointer association could do the job ?

Best regards,

0 Kudos
11 Replies
andrew_4619
Honored Contributor III
722 Views

Why not just allocate(var1,var2,var3(nc,nc),stat=istat ) it will grab some memory of the correct size.

0 Kudos
FortranFan
Honored Contributor III
722 Views

Given the improvements to dynamic memory allocation facility in the language since the Fortran 2003 standard, it's unclear why you'd do need to do such mapping.  And app4619 mentioned, why not use standard language features rather than use malloc?

Things like operations shown in the code below are now fairly easy given the support of standard features in Intel Fortran 16.0:

program p

   !.. local variables
   integer, allocatable, target :: iarr(:)
   integer, pointer :: i1
   integer, pointer :: i2
   integer, pointer :: i3(:,:)
   integer :: nc
   integer :: i
   integer :: j

   iarr = [ (i, i=1,20) ]
   i1 => iarr(1)
   i2 => iarr(2)

   nc = 3
   i3(1:nc,1:nc) => iarr(3:2+nc*nc)

   print *, " i1 = ", i1, " , iarr(1) = ", iarr(1)
   print *, " i2 = ", i2, " , iarr(2) = ", iarr(2)

   write(*,"(*(4x,g0))") "j","i","i3(j,i)","iarr(2+nc*(i-1)+j))"
   do i = 1, nc
      do j = 1, nc
         write(*,"(*(4x,g0))") j, i, i3(j,i), iarr(2+nc*(i-1)+j)
      end do
   end do

   i1 => null()
   i2 => null()
   i3 => null()

   deallocate( iarr, stat=i )

   stop

end program p
  i1 =  1  , iarr(1) =  1
  i2 =  2  , iarr(2) =  2
    j    i    i3(j,i)    iarr(2+nc*(i-1)+j))
    1    1    3    3
    2    1    4    4
    3    1    5    5
    1    2    6    6
    2    2    7    7
    3    2    8    8
    1    3    9    9
    2    3    10    10
    3    3    11    11
Press any key to continue . . .

But any such mapping would involve aliasing (Fortran standard POINTERs) and you would know the need to be most careful with their use.

0 Kudos
netphilou31
New Contributor II
722 Views

The main problem is that I need to gather all the pointers into another structure and pass the pointer on this structure to an external application which in charge of the persistency and the management of the different set of variables corresponding to different calculations conditions and configurations

I had imagined that I could move all the variables belonging to a common block into a derived type that I will allocate at runtime and store the address of this derived type into the main structure. Nevertheless I was looking for another solution which would not require too many changes.

Anyway I am curious about the declaration you wrote. Is it possible to directly allocate a scalar variable ? I thought it was necessary that the variable as the allocatable attribute along with a dimension.

Best regards,

Phil,

0 Kudos
FortranFan
Honored Contributor III
722 Views

netphilou31 wrote:

The main problem is that I need to gather all the pointers into another structure and pass the pointer on this structure to an external application which in charge of the persistency and the management of the different set of variables corresponding to different calculations conditions and configurations

I had imagined that I could move all the variables belonging to a common block into a derived type that I will allocate at runtime and store the address of this derived type into the main structure. Nevertheless I was looking for another solution which would not require too many changes.

Anyway I am curious about the declaration you wrote. Is it possible to directly allocate a scalar variable ? I thought it was necessary that the variable as the allocatable attribute along with a dimension.

Best regards,

Phil,

See this thread: https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/593294

If your "external application" is not in Fortran and your Fortran code is "library" type of code, an option might be to let the external application handle the memory part, as discussed in the above thread.  Note this is just a suggestion, especially because your original post involving malloc's and subsequent query suggest your expertise may be in C, C++ type of languages. 

Re: "Is it possible to directly allocate a scalar variable ?", yes this is supported starting with the Fortran 2003 standard.

Re: " I am curious about the declaration you wrote.. I thought it was necessary that the variable as the allocatable attribute along with a dimension." which one?  Are you curious about [fortran]integer, allocatable, target :: iarr(:)[/fortran] which is the same as [fortran]integer, allocatable, dimension(:), target :: iarr[/fortran] 

0 Kudos
andrew_4619
Honored Contributor III
722 Views

Yes you can allocate a scalar but it needs the allocatable attribute

0 Kudos
JVanB
Valued Contributor II
722 Views

The snippet of code in Quote #1 is using essentially F77+extensions to achieve some purpose which is not completely clear. The f2003 standard has incorporated features which go massively beyond the capabilities you are going to need. Given that, perhaps the best thing is to dream, and to summarize what you would like the compiler to do if only it had essentially unlimited capabilities that could be applied to your problem. It likely is possible that your dreams could be translated into code, so dream big and be specific.

 

0 Kudos
netphilou31
New Contributor II
722 Views

Thanks for all of the replies, I will study the suggestions and read the mentioned thread above.

Thanks again.

0 Kudos
jimdempseyatthecove
Honored Contributor III
722 Views

netphilou31 wrote:

The main problem is that I need to gather all the pointers into another structure and pass the pointer on this structure to an external application which in charge of the persistency and the management of the different set of variables corresponding to different calculations conditions and configurations

From IVF documentation: Contents | Compiler Reference | Mixed Language Programming | Standard Fortran and C Interoperability

subroutine Simulation(alpha, beta, gamma, delta, arrays) BIND(C) 
   use, intrinsic :: ISO_C_BINDING 
   implicit none 
   integer (C_LONG), value :: alpha 
   real (C_DOUBLE), intent(inout) :: beta 
   integer (C_LONG), intent(out) :: gamma 
   real (C_DOUBLE),dimension(*),intent(in) :: delta
   type, BIND(C) :: pass 
      integer (C_INT) :: lenc, lenf
      type (C_PTR) :: c, f 
   end type pass 
   type (pass), intent(inout) :: arrays
   real (C_FLOAT), ALLOCATABLE, target, save :: eta(:)
   real (C_FLOAT), pointer :: c_array(:) 
   ... 
   ! Associate c_array with an array allocated in C 
   call C_F_POINTER (arrays%c, c_array, (/arrays%lenc/) ) 
   ... 
   ! Allocate an array and make it available in C 
   arrays%lenf = 100 
   ALLOCATE (eta(arrays%lenf)) 
   arrays%f = c_loc(eta) 
   ... 
end subroutine Simulation

Jim Dempsey

0 Kudos
jimdempseyatthecove
Honored Contributor III
722 Views
subroutine SendToManagement
   use YourModuleContainingArray
   use, intrinsic :: ISO_C_BINDING 
   implicit none 
   type, BIND(C) :: pass 
      integer (C_INT) :: lenc, lenf
      type (C_PTR) :: c, f 
   end type pass 
   type (pass) :: passArrays

   passArrays%lenc = SIZE(ArrayCinModule)
   passArrays%c = C_LOC(ArrayCinModule)

   passArrays%lenf = SIZE(ArrayFinModule)
   passArrays%f = C_LOC(ArrayFinModule)

   call ManagementSend(passArrays)
end subroutine SendToManagement

The above is a subset of #9 for sending some Fortran arrays to C

Jim Dempsey

0 Kudos
netphilou31
New Contributor II
722 Views

Hi Jim,

Seems to be interresting. I am currently on abusiness trip do I will study this asap.

For your information the external application is in Delphi but I think that it can handle C calling convention.

Thanks,

Phil.

0 Kudos
LRaim
New Contributor I
722 Views

I have followed the discussion but I still do not fully understand the problem.

In any case:

  1. I use 'common' areas containing (in addition to scalars and arrays) pointers to dynamically allocated areas.
  2. I use to swap-out / swap-in their content either to files or other unstructured allocated areas with no problems and without any use of C/C++ interfaces.
  3. A common area when clearly structured provides a simple way to have many variables shared across the various subroutines.

If you provide an example of one of your 'common' areas the problem would be more clear.

Regards   

0 Kudos
Reply