2

Some of my fortran subroutines have a gigantic amount of inputs passed to them, sometimes even 30 or 40. The reason for this is twofold, first, those subroutines have many clearly directly related subroutines which need some of those variables as input, and second, to avoid defining global variables, and the solution for this seems to be to pass every variable to a subroutine explicitly every time.

This seems unacceptable to me, but I don't really have a solution for it, and I am not 100% sure that it is a problem in the first place, perhaps this is the right way to do things in this language.

My question is then: is this a problem? If it is, is there a better way to manage scope in this language, without necessarily introducing objects?

Ignacio
  • 377
  • 3
  • 12
  • 4
    I fear this is opinion-based. Especially to say whether it is a problem or not is opinion-based. I suggest you to read general programming questions and answers like https://stackoverflow.com/questions/174968/how-many-parameters-are-too-many https://softwareengineering.stackexchange.com/questions/145055/are-there-guidelines-on-how-many-parameters-a-function-should-accept Fortran is not that special. Modern Fortran has many features that help you to reduce the number of arguments, especially derived types - structures. – Vladimir F Героям слава Jun 04 '18 at 18:29
  • Notice that one of them is closed ass opinion-based too. Another one https://stackoverflow.com/questions/2244860/when-a-method-has-too-many-parameters – Vladimir F Героям слава Jun 04 '18 at 18:32
  • Also, big project management and your personal role (and what you should or should not change in a legacy project) is also off topic, that would be for softwareengineering.stackexchange.com. – Vladimir F Героям слава Jun 04 '18 at 18:35
  • I don't think this question necessitates (purely, even mainly) opinion-based answers. But to avoid vague answers hedged around with *ifs* and *buts* we need a much more pointed question, I don't think it can be answered (well) in its current form. – High Performance Mark Jun 04 '18 at 19:05
  • I will try to reformat it somewhat. I don't believe the question is opinion based, I feel like there should be a clear cut answer as to whether 30 parameters are too much or not for a subroutine, it seems to me to be a rather extreme case, I am expecting an answer along the lines of "yes, that is totally normal" or "not at all, that is kind of crazy, a better way would be to do such and such". I can edit the off topic parts, I tried to add them for context. – Ignacio Jun 04 '18 at 22:24
  • As @VladimirF mentioned, Object-Oriented Programming (OOP) and derived-type usage would be a good solution. However, one thing to keep in mind is that OOP and performance efficiency are often perpendicular to each other. In similar situations to yours in my own projects, I used to write the non-intensive parts in OOP style, but once reaching the core intensive number-crunching subroutines, I would do everything in bare procedural programming style. – Scientist Jun 05 '18 at 05:20
  • @King This is exactly my problem, I would prefer to avoid OOP because of performance concerns. – Ignacio Jun 05 '18 at 05:29
  • 2
    @Ignacio so long as you stay away from dynamic polymorphism, I don't think if the performance loss due to the use of simple compound types, that only aggregate variables, would be significant (I have not tested it though). – Scientist Jun 05 '18 at 06:31
  • 3
    You don't need OOP, you just use structures - derived types. That is not OOP, that was widely used in Pascal or C even in the 1970s (and earlier in some other languages). – Vladimir F Героям слава Jun 05 '18 at 06:32
  • 1
    With some past CPUs, there could be a measurable performance degradation due to a long list of arguments (compared with COMMON or MODULE variables); there was more than one possible mechanism for it. Interprocedural compiler optimization is the usual method to deal with it. Substituting a derived type wouldn't affect this. – tim18 Jun 05 '18 at 12:15

1 Answers1

4

I can see why the designers want to avoid global variables. I have to work with a code that took the opposite approach, almost no arguments and everything is in the global state in various modules and it is terrible, no matter how much they use the only clause in the use statements.

We can safely say that this amount of arguments (say 30) is way too large. All code style guidelines will probably agree with that. It is often a bit unpleasant to work with the many arguments libraries like LAPACK require, and that is nowhere close to 30.

There are several ways Fortran 90 and more recent can reduce the number of arguments.

Firstly, you can couple logically related variables into a derived type

type particle
  integer :: species
  real    :: mass
  real    :: x, y, z
  real    :: vx, vy, vz
  ...
end type

Secondly, by using assumed shape arrays you can avoid passing the array dimensions. This allows modern LAPACK interfaces to have significantly smaller number of arguments, for example (both the Netlib and the MKL interfaces).

subroutine sub(A, NX, NY, NZ)
  integer :: NZ, NY, NZ
  real :: A(NX, NY, NZ)

vs.

subroutine sub(A)
  real :: A(:,:,:)

This change requires explicit interface for the procedure so in practise the procedures have to be moved into modules.

Both these changes are rather significant changes and require significant refactoring efforts for large legacy codes.