Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
Announcements
FPGA community forums and blogs on community.intel.com are migrating to the new Altera Community and are read-only. For urgent support needs during this transition, please visit the FPGA Design Resources page or contact an Altera Authorized Distributor.
29285 Discussions

Incorrect recompilation ordering (Possible)

acar
Beginner
884 Views
I've noticed that when one makes a change to a subroutine's pass parameters, e.g. adding or removing an argument, and then update the various calls to the subroutine in the VS solution, that building the solution often baulks because it attempts to recompile a routine with a call to the changed subroutine prior to recompiling the changed subroutine. This is not a major issue for me as I can then recompile the changed subroutine and then build the solution successfully. It does, I guess, suggest that the compiler is not properly recording or acting on changes made to the solution?
ACAR.
Further to my last point, I'm seeing issues with the compiler performing a build but not recognising that a subroutine's pass parameters have been modified.
0 Kudos
12 Replies
Steven_L_Intel1
Employee
884 Views
You have hit upon one of the problems with generated interface checking. It depends on the called routine being compiled first, to update the generated interface, but the build dependency order looks only at INCLUDE and USE, not calls. This may not get addressed for a while - all I can suggest is to do a Build > Rebuild if you encounter this issue.
0 Kudos
mecej4
Honored Contributor III
884 Views
But there is a silver lining, too: if all CALLed procedures are placed in modules, as is often recommended, and the caller has an interface to the callee through a USE statement for the module containing the callee, the present build procedure will work perfectly, and there would be no need to use /warn:interfaces.

These facts are worth bearing in mind at least for new code.
0 Kudos
Steven_L_Intel1
Employee
884 Views
I like it - "It's not a bug, it's a feature!"
0 Kudos
Paul_Curtis
Valued Contributor I
884 Views
"...the build dependency order looks only at INCLUDE and USE, not calls"

That's a pretty serious deficiency for a dependency checker. At the very least, this "feature" should appear prominently in the documentation. Nothing wrong with encouraging modularized code, but users should be made aware that the compiler toolset actually requires it.
0 Kudos
Steven_L_Intel1
Employee
884 Views
"requires it"? No, I wouldn't say that. The issue comes up occasionally. I agree, though, that the dependency analyzer could do better here.
0 Kudos
acar
Beginner
884 Views
I think this must be a new 'feature' in XE as I don't recall it from IVF. I recently attempted modularising my code (I've always used modules for declarations but now I tried also adding procedures to modules) and found it a) virtually impossible not to obtain circular dependencies, b) a retrograde step in terms of having easily navigatable code as I had to lump routines into a single file and there appear to be no features in VS for navigating through a file with multiple procedures and c)a considerable time waster since most modules were used extensively throughout parts of the application any modification to a procedure required extensive recompilation. I've subsiquently got rid of the idea and now have modules only for declarations and mostly keep these in seperate files. This is by far the simplest approach for my code much of which was written some years ago now.

The main issue I found with my attempted modularisation was point 'a' above and I'd like to ask a question on this if I may:
My application is an Finite Element application. I have broken the process down into logical parts, i.e. Geometry, Properties, Loads, Mesh, Analysis and Results. Now, for example, Geometry comprises Points, Lines, Surfaces and Solids structures so there is a logical breakdown of procedures that operate on each of these geometric forms and they could be put into appropriate procedural modules. However, there are other routines that operate on more than one of these geometric forms, e.g. moving a point that is connected to a line which may be connected to a surface requires the data structure for lines and surfaces or a routine to copy a surface requires access to the procedures to copy lines and points. So within the point procedure module I need to USE data and possibly procedure modules for lines and surfaces and in thesurface procedure module I would need to USE the line and point procedure modules. Immediately I have issue with circular dependencies! One option would be to put all geometry procedures into a single module but that does not solve the issue since I get similar circularity issues between say Geometry and Loads where loads are applied to geometric entities so a Load procedure module would need access to the Geometry data module and, for example, if I delete a line then I need to update the loads to that affect then the Geometry procedures module needs access to the loads data structure. This circularity of dependencies is I think inherant/natural to the sort of application that I'm writing and I don't see any way of eliminating it. If I were starting from scratch with this application then how could one approach the coding in a modular way?
0 Kudos
jimdempseyatthecove
Honored Contributor III
884 Views
Acar,

I ran into this circular dependency issue years ago and came up with a simple fix

Before fix:

! foo.f90 - one monolithic file
module foo
real :: someData
...
contains
subroutine foofoo(someArgs)
...
end module foo

After fix

! foo.f90 - data only (plus interfaces if desired)
module foo
real :: someData
....
end module foo
---------------------------------
! foo_code.f90 - code only
subroutine foofoo(someArgs)
use foo
...


IOW breakup the data of the module from the contains code of the module. I also add explicit interfaces to the foo_code but that is optional. Note, there is relatively little editing effort toimplimentthis.

Jim Dempsey



0 Kudos
acar
Beginner
884 Views
Thanks Jim. I'd picked up the idea of seperating data and procedures but I still find circularity in the procedural modules - copying a line requires procedures from the point procedure module and moving a point requires procedures from the line procedure module etc. If I understand you correctly then after the fix your procedures are not in modules which is exactly the way I've been working. So, if understood correctly, I'm actually working in a sensible manner - attempting to modularise procedures is perhaps a step too far!
0 Kudos
jimdempseyatthecove
Honored Contributor III
884 Views
>>I'm actually working in a sensible manner - attempting to modularise procedures is perhaps a step too far.

I recognize that you do not want to make a separate module and/or source file per subroutine/function. Perhaps you can go just one step in that direction with a

! point_line_common_code.f90
...

! point_code.f90
...

! line_code.f90

Then when (if) you find additional circular references make a split again. Somewhat like a divide and concur technique keeping the divides at minimum.

Note, only the code files need to be split this way. At some point later, when spare time is available, you might consider splitting the data portions of the modules too.

Jim Dempsey
0 Kudos
acar
Beginner
884 Views
Thanks Jim. Yes actually the data modules are already independent. I think what you suggest is probably a good way forward but probably something for the future when my code is nearer to completion - there remains (it seems to me) the significant re-building overhead and lack of transparency when everything is placed inside a module.
0 Kudos
jimdempseyatthecove
Honored Contributor III
884 Views
>>I think what you suggest is probably a good way forward but probably something for the future when my code is nearer to completion

When your code is near completion you will not be compiling it so often, eh?

On the solution I cleaned-up it has 446 .f90 files in 13 projects (not counting header files and FPP include files). Optimization level at -O3 with IPO turned off. Without the clean-up a Build tended to be equivalent to Rebuild All. Rebuild All takes 5:40 seconds now and that was about what I recall it taking every time I would edit a line of code. After the fix, it it were not ina module data file (a USE xxx file) the Build now takes on the order of 2 seconds.

While you complete your development, how many times to you expect to perform a build. If you are early-on, or have substantial amount of improvements, this could be 100's of times. I do not know how long your Builds take, assume 5 minutes and 200 builds that is 1000 minutes twiddling your thumbs (two days of productivity). YMMV

BTW, since I put in the fix, I may have compiled 1,000's of times (over the last 5-6 years).

I cannot imagine how long this would take with IPO enabled.

Jim
0 Kudos
acar
Beginner
884 Views
Yes that was the idea/hope although possibly a bit too optimistic! Your statistics are fascinating Jim and I'm grateful to you for sharing your experience. Yes, it is of course the thumb twiddling time I want to avoid. The rebuild time for my solution is indeed in excess of five minute - probably more like 15 minutes, which gives more than adequate scope for thumb twiddling.

I think probably that I still have something of a structural issue with the way I've coded my application and it might be the GUI routines (dialogs, menus, toolbars etc) that are the issue. I need to take some time out to think this through now you have provided a route for fixing this problem. Many thanks, ACAR.

0 Kudos
Reply