- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am trying to implement a suballocator for managing the memory consumption of an application.
http://www.memorymanagement.org/articles/alloc.html#suballocator
Thus I want to associate variables (arrays, derived data types, etc.) with specific memory locations.
In C the location of a variable (scalar, array, struct, etc.) in memory (i.e. the address) can be changed by adjusting the pointer.
I am not sure how this could be realized in Fortran? I tried to use cray pointers, but these seem not to work correctly with derived data types. Any suggestions would be greatly appreciated.
http://www.memorymanagement.org/articles/alloc.html#suballocator
Thus I want to associate variables (arrays, derived data types, etc.) with specific memory locations.
In C the location of a variable (scalar, array, struct, etc.) in memory (i.e. the address) can be changed by adjusting the pointer.
I am not sure how this could be realized in Fortran? I tried to use cray pointers, but these seem not to work correctly with derived data types. Any suggestions would be greatly appreciated.
Link Copied
5 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
If I were you, I would try to override the compiler's ALLOCATE and DEALLOCATE routines. In this way, you don't change the user code at all, just the allocation algorithm. Of course, that only applies to ALLOCATABLE variables.
This is not so hard as it seems. The trick is to write your own versions of library-routines for_alloc_allocatable and for_deallocate. If you put them in a source file within the project, and link the rest of the application with Dll version of run-time library, linker will find your "cuckoo eggs" first, and use them instead of library routines, whenever an ALLOCATE statement is executed (or DEALLOCATE).
Here are few old posts of mine, which describe the necessary bits and pieces.
1) Prototypes of for_alloc_allocatable and for_deallocate. There, you can find the routine interfaces, and declarations of Intel Fortran array descriptors Array descriptors are described here, and a more up-to-date version is in your help. Working with array descriptors is rather delicate and error-prone. However, I think (but did not verify) that the compiler fills in all the pieces except the address.
2) A sample implementation of for_alloc_allocatable. This is, however, very simple-minded, because it just forwards the call to for_allocate and fills the returned allocated memory with a bit-pattern; it does not manipulate array descriptors.
Note that memory manager algorithms can be mind-boggling if you try some non-trivial cases. I would rather stick to standard library memory management unless you exactly know what you're doing.
This is not so hard as it seems. The trick is to write your own versions of library-routines for_alloc_allocatable and for_deallocate. If you put them in a source file within the project, and link the rest of the application with Dll version of run-time library, linker will find your "cuckoo eggs" first, and use them instead of library routines, whenever an ALLOCATE statement is executed (or DEALLOCATE).
Here are few old posts of mine, which describe the necessary bits and pieces.
1) Prototypes of for_alloc_allocatable and for_deallocate. There, you can find the routine interfaces, and declarations of Intel Fortran array descriptors Array descriptors are described here, and a more up-to-date version is in your help. Working with array descriptors is rather delicate and error-prone. However, I think (but did not verify) that the compiler fills in all the pieces except the address.
2) A sample implementation of for_alloc_allocatable. This is, however, very simple-minded, because it just forwards the call to for_allocate and fills the returned allocated memory with a bit-pattern; it does not manipulate array descriptors.
Note that memory manager algorithms can be mind-boggling if you try some non-trivial cases. I would rather stick to standard library memory management unless you exactly know what you're doing.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I do not recommend overriding the compiler-supplied routines. The interfaces do change over time. Using C_F_POINTER in conjunction with TRANSFER to convert an integer of the correct size to type C_PTR seems the best approach to me.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
C_F_POINTER works as Steve suggests.
However, if you are trying to manage memory consumption in a general way, well that is what the heap is used for.
If you are trying to improve the performance and/or avoid fragmentation at the expense of some memory consumption then consider allocating arrays of structs (user derived types) and managing pointers to these. This can be done entirely in FORTRAN or you can use a C/C++ scalable allocator together with the C_F_POINTER.
However, using the C/C++ side allocation may introduce problems if your FORTRAN derived types require constructors (e.g. contains an allocatable array who's descriptor requires initialization). Other than for a wipe to 0 initialization, C/C++ allocation may present a problem.
In FORTRAN you can allocate to a pointer to an array of objects and then maintain a pool of these arrays of objects.
something like the following:
Jim Dempsey
However, if you are trying to manage memory consumption in a general way, well that is what the heap is used for.
If you are trying to improve the performance and/or avoid fragmentation at the expense of some memory consumption then consider allocating arrays of structs (user derived types) and managing pointers to these. This can be done entirely in FORTRAN or you can use a C/C++ scalable allocator together with the C_F_POINTER.
However, using the C/C++ side allocation may introduce problems if your FORTRAN derived types require constructors (e.g. contains an allocatable array who's descriptor requires initialization). Other than for a wipe to 0 initialization, C/C++ allocation may present a problem.
In FORTRAN you can allocate to a pointer to an array of objects and then maintain a pool of these arrays of objects.
something like the following:
[fortran]module YourModule type YourType real :: stuff integer :: otherStuff end type YourType integer, parameter :: YourTypePoolSize = 100 type YourTypePool type(YourTypePool), pointer :: next type(YourType) :: objects(YourTypePoolSize) integer :: freeCount logical :: IsFree(YourTypePoolSize) end type YourTypePool type(YourTypePool), pointer :: YourTypePoolHead => NULL() contains function getYourType() type(yourType), pointer :: getYourType type(YourTypePool), pointer :: pool pool => YourTypePoolHead do while(associated(pool)) if(pool%freeCount .gt. 0) then do i=1,YourTypePoolSize if(pool%IsFree(i)) then pool%IsFree(i) = .false. pool%freeCount = pool%freeCount - 1 getYourType => pool%objects(i) return endif pool%freeCount = 0 ! ?? end do endif pool => pool%next end do allocate(pool) pool%IsFree(1) = .false. getYourType => pool%objects(1) pool%freeCount = YourTypePoolSize - 1
do i=2,YourTypePoolSize pool%IsFree(i) = .true. end do end function getYourType subroutine returnYourType(obj) type(yourType), pointer :: obj type(YourTypePool), pointer :: pool pool => YourTypePoolHead do while(associated(pool)) if((loc(obj) .ge. loc(pool%objects(1))) .and. (loc(obj) .le. loc(pool%objects(YourTypePoolSize)))) then do i = 1, YourTypePoolSize if(loc(obj) .eq loc(pool%objects(i))) then pool%IsFree(i) = .true. pool%freeCount = pool%freeCount + 1 return endif end do endif end do ! error end subroutine returnYourType subroutine cleanupYourType type(YourTypePool), pointer :: pool pool => YourTypePoolHead do while(associated(pool)) YourTypePoolHead = YourTypePoolHead%next deallocate(pool) end do end subroutine cleanupYourType end module YourModule [/fortran]
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Quoting Steve Lionel (Intel)
I do not recommend overriding the compiler-supplied routines. The interfaces do change over time. Using C_F_POINTER in conjunction with TRANSFER to convert an integer of the correct size to type C_PTR seems the best approach to me.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you for your suggestions. I will have a look at C_PTR pointers and the C_F_POINTER routine.

Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page