- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am writing some F90 interfaces to the Sparskit2 library that are intended to make the F90 code look as much like Matlab as possible (Before you say anything, I am engaged in porting a fairly large code from one to the other!).
For example, I want to be able to add sparse matrices, defined as
type,public :: CSR !COMPRESSED SPARSE ROW matrix
real*8,pointer :: a(:) !contains NNZ data values
integer*4,pointer :: jc(:)!contains NNZ column indices
integer*4,pointer :: ia(:)!contains NROW+1 indices to a/jc
integer*4 :: ncol !number of columns
end type CSR
by writing
A=B+C. With A, B and C being TYPE CSR
To this end, I have written something that works nicely:
FUNCTION SpaAdd(a,b) ! overloads '+' for sparse a and b
!
bunch of declarations and code
!
ALLOCATE(SpaAdd%a(nzmax),SpaAdd%jc(nzmax),SpaAdd%ia(nrow+1)) !nzmax determined in code above
!
assignments to SpaAdd using Sparskit2 subroutines
!
END FUNCTION SpaAdd
Am I asking for memory leakage by doing this, or does FORTRAN9x automatically de-allocate the components of the result in the calling unit?
I cannot find any answer to this question in the manuals that I have to hand nor by web search.
Alternatively, is there a tool that I can use, either on Tru-64 Unix or Win98, that will allow me to track allocated memory?
I have a solution, if the above does cause memory leakage, but it is clumsier - allocate the to a SAVEd target TYPE(CSR) and point SpaAdd to it.
Paul Thomas
For example, I want to be able to add sparse matrices, defined as
type,public :: CSR !COMPRESSED SPARSE ROW matrix
real*8,pointer :: a(:) !contains NNZ data values
integer*4,pointer :: jc(:)!contains NNZ column indices
integer*4,pointer :: ia(:)!contains NROW+1 indices to a/jc
integer*4 :: ncol !number of columns
end type CSR
by writing
A=B+C. With A, B and C being TYPE CSR
To this end, I have written something that works nicely:
FUNCTION SpaAdd(a,b) ! overloads '+' for sparse a and b
!
bunch of declarations and code
!
ALLOCATE(SpaAdd%a(nzmax),SpaAdd%jc(nzmax),SpaAdd%ia(nrow+1)) !nzmax determined in code above
!
assignments to SpaAdd using Sparskit2 subroutines
!
END FUNCTION SpaAdd
Am I asking for memory leakage by doing this, or does FORTRAN9x automatically de-allocate the components of the result in the calling unit?
I cannot find any answer to this question in the manuals that I have to hand nor by web search.
Alternatively, is there a tool that I can use, either on Tru-64 Unix or Win98, that will allow me to track allocated memory?
I have a solution, if the above does cause memory leakage, but it is clumsier - allocate the to a SAVEd target TYPE(CSR) and point SpaAdd to it.
Paul Thomas
Link Copied
10 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Am I asking for memory leakage by doing this,
yes :-(
or does FORTRAN9x automatically de-allocate the components of the result in the calling unit?
no it doesn't.
However :), CVF6.6 now implements Allocatable Components TR from Fortran 2000 standard -- this should be the solution. Under this extension, TYPE components can be ALLOCATABLE, and are automatically deallocated when the owner goes out of scope. It has few other niceties, such as assignment. When csrA and csrB have POINTER components, statement csrA = csrB means
csrA%a => csrB%a
csrA%jc => csrB%jc
csrA%ia => csrB%ia
(You can to override that behaviour using INTERFACE ASSIGNMENT(=)). However, with ALLOCATABLE components, it means
ALLOCATE(csrA%a(SIZE(csrB%a)), csrA%jc(SIZE(csrB%jc))...
csrA%a = csrB%a
csrA%jc = csrB%jc etc.
I'm still getting familiar with it, so I can't tell you all pecularities in advance (e.g. what happens if csrA%a is already ALLOCATEd before assignment above). Check the CVF documentation. F2000 draft document is available [url=http://www.j3-fortran.org]here[/here].
Jugoslav
yes :-(
or does FORTRAN9x automatically de-allocate the components of the result in the calling unit?
no it doesn't.
However :), CVF6.6 now implements Allocatable Components TR from Fortran 2000 standard -- this should be the solution. Under this extension, TYPE components can be ALLOCATABLE, and are automatically deallocated when the owner goes out of scope. It has few other niceties, such as assignment. When csrA and csrB have POINTER components, statement csrA = csrB means
csrA%a => csrB%a
csrA%jc => csrB%jc
csrA%ia => csrB%ia
(You can to override that behaviour using INTERFACE ASSIGNMENT(=)). However, with ALLOCATABLE components, it means
ALLOCATE(csrA%a(SIZE(csrB%a)), csrA%jc(SIZE(csrB%jc))...
csrA%a = csrB%a
csrA%jc = csrB%jc etc.
I'm still getting familiar with it, so I can't tell you all pecularities in advance (e.g. what happens if csrA%a is already ALLOCATEd before assignment above). Check the CVF documentation. F2000 draft document is available [url=http://www.j3-fortran.org]here[/here].
Jugoslav
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Let me warn you about a potential "gotcha" using ALLOCATABLE function results - CVF will (as of when I write this) not deallocate the result until the caller leaves its scope - that is, the function result behaves as if it were a local variable in the calling routine. This can be a problem if you call the function in a loop, as there will be a memory leak.
We know that this is not the ideal situation, and intend to resolve it sometime in the future.
Steve
We know that this is not the ideal situation, and intend to resolve it sometime in the future.
Steve
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
IMO array-valued function results should be avoided anyway -- I can only guess how many troubles it creates to compiler writers to get them right; and performance is due to be poor because of (almost) unavoidable copy-in/copy-out of the result.
I think the feature in question won't be an issue for the original poster. What about the situation I mentioned above (components already allocated before the assignment)?
Jugoslav
I think the feature in question won't be an issue for the original poster. What about the situation I mentioned above (components already allocated before the assignment)?
Jugoslav
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Oh, do return values which are TYPEs containing allocatable components fall to the same category as allocatable return values in this regard?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
If I recall correctly, in the case you have above, the previous storage is automatically deallocated, if needed, before a new allocation.
Yes, I think types with allocatable components behave the same for function results. In both cases, the compiler has to construct a temporary for the return value.
Steve
Yes, I think types with allocatable components behave the same for function results. In both cases, the compiler has to construct a temporary for the return value.
Steve
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Please find below a reply from John Reid. Note that he was courteous enough not to tell me to read his book, which contains exactly what I needed to know!!
THOMAS Paul Richard wrote:
> Dear John,
> I am sorry to trouble you but I wonder if you can help me with the question
> below that I just posted on the INTEL forum board? I have written a number
> of sparse matrix functions to overload operators. The functions are TYPEd
> as sparse (TYPE(CSR)) and so contain array pointers in the result. I can
> find no discussion anywhere of what I can assume about deallocation of the
> memory following the call to the function. I have found many examples of
> this kind of usage on the web. Am I going to generate memory leaks?
Yes. This has been recognized for years within the Fortran committees and there is an ISO Technical Report (a sort of mini standard) that addresses it as an extension of Fortan 95. Actually, it was nearly added
to Fortan 95, but was not quite ready in time. It is to use allocatable components instead of pointer components. This means that the compiler can arrange for deallocation to happen whenever the parent object ceases to exist (as long as the object does not have the pointer or target
attribute).
The feature is guaranteed for Fortran 2000 and is already implemented in most of the compilers. I suggest that you use it if your compiler has it, or else regard using pointer components as a temporary measure. Some
compilers do have automatic garbage collection, but it is a good idea not to rely on this.
Best wishes,
John.
THOMAS Paul Richard wrote:
> Dear John,
> I am sorry to trouble you but I wonder if you can help me with the question
> below that I just posted on the INTEL forum board? I have written a number
> of sparse matrix functions to overload operators. The functions are TYPEd
> as sparse (TYPE(CSR)) and so contain array pointers in the result. I can
> find no discussion anywhere of what I can assume about deallocation of the
> memory following the call to the function. I have found many examples of
> this kind of usage on the web. Am I going to generate memory leaks?
Yes. This has been recognized for years within the Fortran committees and there is an ISO Technical Report (a sort of mini standard) that addresses it as an extension of Fortan 95. Actually, it was nearly added
to Fortan 95, but was not quite ready in time. It is to use allocatable components instead of pointer components. This means that the compiler can arrange for deallocation to happen whenever the parent object ceases to exist (as long as the object does not have the pointer or target
attribute).
The feature is guaranteed for Fortran 2000 and is already implemented in most of the compilers. I suggest that you use it if your compiler has it, or else regard using pointer components as a temporary measure. Some
compilers do have automatic garbage collection, but it is a good idea not to rely on this.
Best wishes,
John.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
What book did John Reid write?
Mike
Mike
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It should be "Fortran 90/95 Explained" by Michael Metcalf and John Reid. If you need to write Fortran 90/95 code, in my opinion, this book needs to be beside your computer.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Yes, an excellent book. Highly recommended.
Steve
Steve
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Yes, this is indeed the book. I wish that I had it by my computer when I embarked on this job! I had the NAG guide with me, which is OK until one gets to murkier stuff like this.
For the time being, I have converted all the overloaded operators into subroutines, so that all pointers can be deallocated within the scoping unit. The converted code now works fine and, as far as I know, the only memory leaks are by commission, rather than omission.
However, I have become a bit obsessed about the potential to port directly from one langauge to the other. To this end I have started on a sparse library that users a target working array, contained in its very own module. Each sparse function points to chunks of this working array, above an index, and the sparse assignment interface resets the index to 1. Thus all the remaining memory allocated to sparse variables can be deallocated within the scoping unit. There is a slight penalty of tying up the memory in the form of the working array, but this is better than its going down the tube...
If anybody is interested, I'll post the result when satisfied.
For the time being, I have converted all the overloaded operators into subroutines, so that all pointers can be deallocated within the scoping unit. The converted code now works fine and, as far as I know, the only memory leaks are by commission, rather than omission.
However, I have become a bit obsessed about the potential to port directly from one langauge to the other. To this end I have started on a sparse library that users a target working array, contained in its very own module. Each sparse function points to chunks of this working array, above an index, and the sparse assignment interface resets the index to 1. Thus all the remaining memory allocated to sparse variables can be deallocated within the scoping unit. There is a slight penalty of tying up the memory in the form of the working array, but this is better than its going down the tube...
If anybody is interested, I'll post the result when satisfied.
![](/skins/images/872293744008A34B36F8ABF94A46CC66/responsive_peak/images/icon_anonymous_message.png)
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