For small pure/elemental functions like this, should we prefer to pass real/integer arguments as
I’m mainly asking, because in C/C++, passing by value in such cases, is optimal, and we shouldn’t pass by pointers.
But in Fortran, everything is passed as pointers, and I don’t know if there’s any benefit to pass by
value, as it’s mostly used for interoperability with C.
It won’t probably make any performance difference, because, in most cases, compilers are smart enough to optimize things perfectly.
But still it’s nice to know what’s the preferred way of doing this, as many small and crucial functions like this will be used everywhere.
In a fortran subprogram, passing by value usually means that the compiler makes a copy and then passes the address of that copy to be associated with the dummy argument. Inside the subprogram, the dummy argument can be modified, but its value is not passed back to the actual argument. It is like copy-in without the copy-out.
You can do the same thing by passing the actual argument to an intent(in) dummy argument, and then inside the subprogram a local copy is made that can be modified. The value attribute is syntax sugar to do that.
When a fortran subprogram calls a C function where the dummy argument in the interface block has the value attribute, that means that the value of the actual argument is placed on the stack to match the C calling convention.
The value attribute does different things depending on the context.
In Fortran, as you mentioned, arguments are typically passed by reference, which means that the function operates on the actual data passed to it rather than a copy. This is a bit different from C/C++, where passing by value (i.e., making a copy of the data) is more common for small or primitive data types like integers or floats.
Here are some considerations for choosing between passing by value and passing by reference in Fortran, especially for small, elemental functions:
- Default Behavior: In Fortran, the default behavior is to pass arguments by reference. This is efficient for large data structures, as it avoids the overhead of copying. For small, simple data types, the difference in efficiency between pass-by-reference and pass-by-value is usually negligible.
- Intent Attribute: Fortran allows you to specify the
intent attribute for function arguments (
inout). This can help with code readability and correctness but doesn’t change the underlying pass-by-reference mechanism.
- Pass-by-Value for Interoperability: As you pointed out, Fortran supports passing arguments by value mainly for interoperability with C. This is done using the
value attribute in the function declaration. It’s not commonly used in pure Fortran code unless there’s a specific need for it.
- Compiler Optimizations: Modern Fortran compilers are quite good at optimizing code, so the difference in performance between pass-by-value and pass-by-reference for small data types is often minimal. The compiler may even inline small functions, eliminating the overhead of passing arguments altogether.
- Readability and Coding Standards: Sometimes the decision might be driven more by coding standards and readability. If your codebase or team has established practices, it’s often best to adhere to those.
- Safety: Passing by reference means the function could potentially modify the input variable. If this is not desired, pass-by-value can enforce immutability. In Fortran, this can be managed with the
intent(in) attribute, signaling that the function should not modify the input.
In conclusion, for small, elemental functions in Fortran, the choice between pass-by-value and pass-by-reference often comes down to considerations of interoperability, coding standards, and readability, rather than performance. In most cases, sticking with the default pass-by-reference approach, possibly combined with appropriate
intent attributes, is a sound practice in Fortran. However, if you’re working in a context where interoperability with C is important, using pass-by-value where appropriate can be beneficial