- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
Link Copied
12 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
These facts are worth bearing in mind at least for new code.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I like it - "It's not a bug, it's a feature!"
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
"...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.
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
"requires it"? No, I wouldn't say that. The issue comes up occasionally. I agree, though, that the dependency analyzer could do better here.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
>>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
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
>>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
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.

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