- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have a problem with the following piece of code (see below). As I run it, it falls over when JBUF reach size
3.200.000.
C-------------------------------------------------
INTEGER, POINTER :: IBUF(:), JBUF(:)
INTEGER NUM, NEW
NUM=1 000 000
NEW=100 000
10 CONTINUE
ALLOCATE ( IBUF(NUM) )
ALLOCATE ( JBUF(NUM) )
JBUF=IBUF
cc DO I=1,NUM
cc JBUF(I)=IBUF(I)
cc ENDDO
DEALLOCATE (IBUF)
DEALLOCATE (JBUF)
NUM=NUM+NEW
go to 10
END
C-------------------------------------------------
Debugging with Valgrind I noticed that the problem has something to do with the stack size, and in fact if I change the stack size (eg: %> limit stacksize unlimited ) then the problem seem to be solved, or say it is postponed;) Equally, it works fine if I use the compiler flag "-heap-arrays" when compiling.
Now the question is: why is a dynamic array allocated on the stack at all?
Furthermore, if I change only JBUF from POINTER to ALLOCATABLE, and I keep the rest of the code as is, then my test run fine, even with the original stack size (=10240 kbytes). This seems to imply that the problem is in JBUF only.
IBUF seems to never overflow, and in fact I believe it is allocated on the heap. Can anyone explain me this behaviour? I mean, both JBUF and IBUF are arrays made out of a pointer, but the first is on the stack whereas the other on the heap. Why?
And finally, does anybody know why if I turn JBUF from POINTER to ALLOCATABLE, then it goes on the heap?
Apologise for the long post;)
Any help will be much appreciated! Luca
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
one more thing:
if I keep the code as is, but I uncomment the do loop and I comment out the assignment (JBUF=IBUF), then again, it run smoothly.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Maybe others can extend/correct as needed.
With the POINTER attribute, the assignment JBUF=IBUF leads to use of an array temporary due to the compiler's concern for potential memory overlap between the arrays.
JBUF does not live on the stack, it lives on the heap, but it is the case that a very large temporary the size of NUM is created on the stack due to the array assignment. As you found, the array temporary is avoided when JBUF is declared with the ALLOCATABLE attribute or when accessing a single element at a time in the loop.
The earlier forum thread (here) contains lots of related discussion.
Hope that helps.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
yes thanks Kevin!!
One more thing though. I haven't made any test yet, but I was thinking that in terms of performance, creating a temporary can probably lead to slower code (cause of course it has to copy the buffer on the temporary) and therefore i might be better off avoding that altogether.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
That's correct. There is a performance cost associated with the temporary. Guidance I've received in other similar cases and recommendations by othersthat I've read is to use the ALLOCATABLE for dynamic arrays unless there's a need for POINTER.
In the thread I cited, Steve has a nice succinct reply (here), writing:
"If you want "dynamic arrays", use ALLOCATABLE. If you want to be able to have pointers that can point to parts of other arrays, use POINTER."
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
>>With the POINTER attribute, the assignment JBUF=IBUF leads to use of an array temporary due to the compiler's concern for potential memory overlap between the arrays.
Why not (write and) use a variant of memmove with enhancement for stride? One that performs the "copy" without use of temporary. If you look back at the number of forum posts related to problems with temporaries use in A = B copy operations you should find it well worth the effort to provide and use a Fortran analog to memmove.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I will put forth the suggestion Jim.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Okay thanks guys! But then I start wondering where else to expect a temporary to kick in.
I mean, is there any other situation I should be careful of?
I did some reading on both the ifort manual and the web, and it is my understanding that they are created not only when copying two arrays with pointers (see above) but also when passing a dynamic array made with pointer to a subroutine expecting an explicit array (sorry if the terminology is not exactly the correct one).
Can you briefly post me an example of the scenario i mentioned above (passing a dyn array to a routine expecting a f77 array)? as I tried to write a test and I could not see any performance penalty.
Many thanks, Luca
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In the case of passing an argument, the compiler does a run-time check to see if what you are passing is contiguous. If it is, then it doesn't need to make a copy (when the receiving dummy argument is not known to be a deferred-shape array). This is different than a test for overlap, which the compiler is doing for the assignment. In many cases the compiler can figure it out, but for POINTER it does not have enough information at compile-time to tell.
If you use ALLOCATABLE arrays you will not have this problem.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page