- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
I just upgraded to Intel Fortran Compiler which comes with Parallel Studio XE 2018 (Initial Release). This version of ifort no longer compiles this piece of code:
SUBROUTINE MOO COMMON /BLOCK/ FOO !$OMP THREADPRIVATE (/BLOCK/) REAL BAR EQUIVALENCE ( FOO, BAR ) RETURN END
$ ifort --version
ifort (IFORT) 18.0.0 20170811
Copyright (C) 1985-2017 Intel Corporation. All rights reserved.
$ ifort -qopenmp -o foo -c foo.f
foo.f(2): error #7903: A variable in a THREADPRIVATE directive must not be an element of a common block or be declared in an equivalence statement. [FOO]
COMMON /BLOCK/ FOO
---------------------^
compilation aborted for foo.f (code 1)
Now I realize that use of threadprivate variables in equivalence statements is forbidden by the OpenMP standard. It is also true that gfortran also does not compile this piece of code. However, ifort versions 17.0.4 and before did compile the above fine so it appears that ifort has gotten more strict when it comes to enforcing the standard. So apparently the only way forward is to fix the code.
But given that the real code which shows this problem in our application was written by a third party and is enormous, where the interleaving of threadprivate and equivalenced variables runs very deep this option is not really feasible, so here comes my question:
Is there a flag for ifort which makes the compiler accept the above piece of code, or is there really no way around fixing the code?
Cheers, Bastian
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Typically in the situation where a coding error had previously gone undetected, and now is detected, there is no "flag" to back off the check. I tried to see if -diag-disable would allow disabling this error, but it would not. It is quite common for new versions to add checks for errors that previous versions missed.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Would using fpp and -DFOO=BAR be sufficient for a work around? (it may have too large of scope)
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Maybe Jim, what do you have in mind?
Bastian
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Bastian B. wrote:
.. or is there really no way around fixing the code?
How about this?
SUBROUTINE MOO COMMON /BLOCK/ FOO !$OMP THREADPRIVATE (/BLOCK/) CALL BOO() RETURN END SUBROUTINE BOO COMMON /BLOCK/ FOO REAL BAR EQUIVALENCE ( FOO, BAR ) RETURN END
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
FF that is interesting. Not sure what will happen. My guess is you will have BLOCK declared as residing in two different segments, and thus result in a Linker error/warning about duplicate symbol.
I think the "correct" route would be:
SUBROUTINE MOO COMMON /BLOCK/ FOO !$OMP THREADPRIVATE (/BLOCK/) CALL BOO() RETURN END SUBROUTINE BOO COMMON /BLOCK/ BAR !$OMP THREADPRIVATE (/BLOCK/) REAL BAR ... RETURN END
Though that will (may) require some edits. If the COMMON's are brought into the Fortran source via Fortran INCLUDE this might not require too much editing for Bastien.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
jimdempseyatthecove wrote:
.. Not sure what will happen. .. I think the "correct" route would be:..
It seems like OP will then be back to square one given the need to EQUIVALENCE BAR with FOO.
Another option for OP to try is doing away with EQUIVALENCE and use the TRANSFER intrinsic:
SUBROUTINE MOO COMMON /BLOCK/ FOO !$OMP THREADPRIVATE (/BLOCK/) REAL BAR BAR = TRANSFER( SOURCE=FOO, MOLD=BAR ) RETURN END
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'm not sure if the original poster is the one that contacted Intel Support, but we've been having a long discussion about this internally, and we'll have a reply shortly.
--Lorri
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
FortranFan,
Bastien will have to decide what works for his code.
IMHO a typical Fortran procedure uses EQUIVALENCE to repurpose locations in a COMMON block, once EQUIVALENCE'd the programmer should be obliged to follow Fortran's "Thow shalt not alias variables" rules and use the equivilance'd name throughout the procedure and NOT use the former name (in that procedure). Of potential aliases, pick one.
The #7 post will not work in most cases because BAR becomes a local variable to MOO and thus should the procedure write to BAR (or called procedure modifies /BLOCK/ FOO) the local BAR and global addresses where FOO resides have contents that are out of sync.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
jimdempseyatthecove wrote:
.. Bastien will have to decide what works for his code. ..
The #7 post will not work in most cases because BAR becomes a local variable to MOO and thus should the procedure write to BAR (or called procedure modifies /BLOCK/ FOO) the local BAR and global addresses where FOO resides have contents that are out of sync. ..
Indeed OP has to ultimiately figure out how to proceed, possibly have to TRANSFER back from BAR to FOO:
SUBROUTINE MOO COMMON /BLOCK/ FOO !$OMP THREADPRIVATE (/BLOCK/) REAL BAR BAR = TRANSFER( SOURCE=FOO, MOLD=BAR ) ! Do work with BAR .. ! Transfer byte contents back to FOO FOO = TRANSFER( SOURCE=BAR, MOLD=FOO ) RETURN END
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks everyone for the suggestions, We'll see what we can do.
Lorri - No, I did not contact Intel Support before, but I am looking forward to your reply.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
FortranFan,
That will work ... provided that subroutine MOO does not call anything before it exits that:
a) the called procedure modifies FOO (and expects the caller to observe the modification)
b) MOO modifies BAR, then calls a procedure that uses FOO
Jim Dempsey
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page