- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
A lot of effort is being made at Intel in the direction of multi-threaded programming. Unfortunately, advancement in compiler updates are not multi-threaded programming friendly as the should be.
Using IVF 10.0.027 broke code by making thread-safe code into thread-unsafe code. In my subroutines I typically use pointers to user defined type structures.
type(T_foo), pointer :: a_foo
Up until 10.0.027 this would creat stack local storage for the pointer. 10.0.027 made the pointer SAVE (i.e. the pointer itself stored in static memory as opposed to on stack). This was particularly annoying since it took me a week to figure this out. Code that had been working for years was now broken.
To correct for this, I now have to use
type(T_foo), automatic, pointer :: a_foo
Why, in light of multi-threaded programming,cannot the absense of SAVE imply use stack local storage?
Jim Dempsey
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The default is "auto_scalar" which means that scalars are automatic by default, but non-scalars (derived types and arrays) are static. If you are doing threaded programming, you must use the RECURSIVE keyword or the /auto switch as this will not only default variables to automatic storage, but will also put descriptors and other non-user-visible state on the stack. Note that if you use /Qopenmp or /parallel you get /auto along for the ride. It is not sufficient to just make individual variables automatic.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The default is "auto_scalar" which means that scalars are automatic by default, but non-scalars (derived types and arrays) are static. If you are doing threaded programming, you must use the RECURSIVE keyword or the /auto switch as this will not only default variables to automatic storage, but will also put descriptors and other non-user-visible state on the stack. Note that if you use /Qopenmp or /parallel you get /auto along for the ride. It is not sufficient to just make individual variables automatic.
The routines are not recursive, they are reentrant. I do not desire to use auto parallelization (/parallel) nor to use OpenMP (/Qopenmp) yet I also want the subroutines generated to be thread-safe. I will enable /Qauto and hope that future updates do not change in behavior.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Whether or not they are recursive, I recommend the RECURSIVE keyword be used to get the behavior you want in lieu of switches. You can use the switch if you want.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Whether or not they are recursive, I recommend the RECURSIVE keyword be used to get the behavior you want in lieu of switches. You can use the switch if you want.
Recursive did not make the pointera stack variable, automatic did, so I would imagine /Qauto would as well. /Qauto seemed to correct the problem although I did not inspect the 100's of affected files to verify.
Jim
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
RECURSIVE should have made the pointer a stack variable. If it didn't, that's a bug. I tested with 10.1.026 and 11.0.066 and it did work for me. If you have a test case that shows otherwise i'd like to see it.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
RECURSIVE should have made the pointer a stack variable. If it didn't, that's a bug. I tested with 10.1.026 and 11.0.066 and it did work for me. If you have a test case that shows otherwise i'd like to see it.
Steve,
I ran a test with RECURSIVE, this works. (reenterant alonedoes not work)
10.0.027 WinXP x64 /Debug
Jim
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
If you mean the /reentrancy option, all that does is tell the run-time library whether or not to protect itself against calls from multiple threads.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
If you mean the /reentrancy option, all that does is tell the run-time library whether or not to protect itself against calls from multiple threads.
Luckily, I saw this thread and recalled that something is fishy in Qsave/recursive field. Then, I discovered that we inadvertently left /Qsave for the Release configuration (heritage from prehistory, but shouldn't matter for the semantics), then I joined the pieces together... Otherwise, I don't know how I would find the problem, as the actual example was quite complex.
Steve, you do have a bug there, at least in 11.0.61 (haven't checked 11.0.66). Take a look at the following code:
[cpp]program Qsave call foo(3) end program Qsave recursive subroutine foo(n) implicit none integer, intent(in):: n integer:: j write(*,"(i1)",advance="no") n do j=1,n call foo(n-1) end do end subroutine foo
[/cpp]
It should produce:
3210102101021010
However, when it's compiled with /Qsave, it produces:
3210
Because J is SAVEd accross recursive calls, i.e. shared among all instances. In other words, RECURSIVE doesn't override /Qsave, although it should.
I reported it to Premier as 529970.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Yes, RECURSIVE should override /Qsave. Thanks for reporting it.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page