Does over-using function calls affect performance? Specifically in Fortran
Asked Answered
H

4

5

I habitually write code with lots of functions, I find it makes it clearer. But now I'm writing some code in Fortran which needs to be very efficient, and I'm wondering whether over-using functions will slow it down, or whether the compiler will work out what's going on and optimise?

I know in Java/Python etc each function is an object, and so creating lots of functions would require them to be created in memory. I also know that in Haskell the functions are reduced into each other, so it makes little difference there.

Does anyone know about the case with Fortran? Is there a difference with using intent/pure functions/declaring fewer local variables/anything else?

Hallux answered 9/7, 2010 at 16:32 Comment(4)
In what way is each function an object in Java? Calling a function doesn't create an object... it might do in Python, but I doubt it. (You can fetch a representation of a method in Java via reflection, but that's not the same thing.)Sealey
Sorry, that wasn't very clear. I was referring to the way that anonymous functions in Java (and Python) need to be created and stored in memory, which is time-consuming. If all the local variables in my functions need creating/memory allocating for them each time then it's probably worth using fewer functions, but if they're allocated memory at the start then it probably doesn't make much difference. It was a poor choice to call them 'objects' in memory (though I think they actually are in Python).Hallux
Local variables are created in one instruction and deleted in one instruction if they are on the stack.Jeraldjeraldine
"We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil" --by Donald KnuthWun
J
9

Function calls carry a performance cost for stack based languages, like Fortran. They have to add on to the stack and such.

Because of this, most compilers will try to inline function calls aggressively, if it is possible. Most of the time the compiler will make the right choice on whether or not to inline certain functions in your program.

This automatic inlining process will mean that there is no extra cost for writing your function (at all).

This means that you should write your code as cleanly and organized as possible, and it is likely that the compiler will do these optimizations for you. It is more important that your overall strategy for solving the problem is the most efficient than worry about performance of function calls.

Jeraldjeraldine answered 9/7, 2010 at 16:47 Comment(0)
L
2

Just write the code in the simplest and most well-structured way you can, then when you have it written and tested you can profile it to see if there are any hotspots which require optimisation. Only at that point should you concern yourself with micro-optimisations, and this may not even be necessary if your compiler is doing its job.

Lunate answered 9/7, 2010 at 16:36 Comment(0)
W
1

I've just spent all morning tuning an app consisting of mixed C and Fortran, and of course it uses a lot of functions. What I found (and what I usually find) is not that functions are slow, but that certain function calls (and very few of them) don't really have to be done at all. For example, clearing memory blocks, just to be neat, but doing it at high frequency.

This is not a function of language, and not really a function of inlining either. Function calls could be free and you would still have the problem that the call tree tends to be more bushy than necessary. You need to find out where to prune it. This is the "profiling" method I rely on.

Whatever you do, find out what needs to be fixed. Don't Guess. Many people don't think of this kind of question as guessing, but when they find themselves asking "Will this work, will that help?", they're poking in the dark, rather than finding out where the problems are. Once they know where the problems are, the fix is obvious.

Whinny answered 9/7, 2010 at 18:52 Comment(0)
C
0

Typically subroutine / function calls in Fortran will have very little overhead. While the language standard doesn't specify argument passing mechanisms, the typical implementation is "by reference" so no copying is involved, only setting up a new procedure. On most modern architectures this has little overhead. Selecting good algorithms is generally far more important than micro-optimizations.

An exception about calling be quick could be case in which the compiler has to create temporary arrays, for example, if the actual argument is a non-contiguous array subsection and the called procedure argument is a plain contiguous array. Suppose that the dummy argument is dimension (:). Calling it with an array of dimension (:) is simple. If you request a non-unit stride in the call, e.g., array (1:12:3), then the array is non-contiguous and the compiler may need to create a temporary copy. Suppose that the actual argument is dimension (:,:). If the call has array (:,j), the sub-array is contiguous since in Fortran the first index varies fastest in memory and shouldn't need a copy. But array (i,:) is non-contiguous and might require a temporary copy.

Some compilers have options to warn you when temporary array copies are needed so that you can change your code, if you wish.

Cathrinecathryn answered 9/7, 2010 at 17:22 Comment(1)
You're right, of course, but there's a point that people miss. These things are relative, not just fast or slow. When a routine is entered and exited, it has a bunch of things to do. If it spends more than about 5% of total time doing that, like if it's calling a routine that in general could do something complex, but typically does very little, then samples should find it, and some changes should be made. Example: LSAME in LAPACK typically just compares two characters, but that guy was on the radar way too much.Whinny

© 2022 - 2024 — McMap. All rights reserved.