Topic: speed designs questions

I might come up with more questions in this category, but for now ...
If I have a loop that runs a million times, and within that loop I am converting 5 and 6 digit long numbers (sometimes shorter, sometimes a bit longer) from one base to another, is it faster to keep the math conversion statements in the main code or to create a function that does the calculations (with the number as a parameter) and passes back the answer?

I don't know what the compiler does with that. By calling the function, I'm adding overhead. But making the functional "tool" makes the program more tidy.  If we are talking about and execution difference in seconds or a minute for the whole loop to process the function call, I can live with that and a "cleaner" program. But if it adds 10 minutes, I'd leave the code in the main area.

Re: speed designs questions

I almost always err on the side of cleaner code.  The time spent "jumping" to a function one million times is going to be negligible on modern hardware, especially if you're passing in a single argument.  By "negligible," I mean that the jump, even occurring one million times, might not consume a measurable amount of time in total.  If you have optimizations on, there's even a chance that the compiler might decide to "inline" your function call itself, effectively removing the jump operation entirely and performing the operation right where the call was to be made.

Fortran doesn't have a general way to force a function to be inlined, though.  However, if you mark your function as PURE in Fortran, it can improve the optimizations that the compiler can perform.  The PURE modifier basically tells the compiler that your function takes exactly the inputs provided and outputs exactly one value without any side effects (like printing or changing an input).

If you have an array of values to convert, you can even mark your function as ELEMENTAL and pass the entire array at once, allowing the compiler to further optimize the procedure and calling it however it would like.

Basically, though, I would keep the conversion in a function.  The cost of one call, even one million times, just isn't measurable.

Jeff Armstrong
Approximatrix, LLC

3 (edited by designer 2025-12-02 00:09:40)

Re: speed designs questions

Thank you Jeff. This code solves problems I need to change a little bit each time. So keeping the parts that don't change (base conversion) from those that do, helps prevent mistakes. It can take a while to find a missing parenthesis, with the error message "Missing EndIF".

I'll look for the PURE and ELEMENTAL designations but if you have the time, could you please point me in the direction to look for them. Before this last update, for another problem, you had me change a compiler setting from Native to Generic.

I don't see that compiler setting (Native vs Generic) in the latest Apple Silcone release (Version 3.41, Build 4440).

Re: speed designs questions

designer wrote:

I'll look for the PURE and ELEMENTAL designations but if you have the time, could you please point me in the direction to look for them.

There's a simple writeup of elemental functions here.  Essentially, the function accepts and returns a scalar value, but, since it is marked elemental, you can just pass an array to the function, and the function will be called on each element of said array, returning another array where every value is the return value from the function for its corresponding input element. 

For example, we can write a trivial elemental function that doubles a number:

elemental function double_it(x)
implicit none

    real::double_it
    real, intent(in)::x
    
    double_it = 2.0*x
    
end function double_it

Now, in our calling routine, we could have this:

    real, dimension(4)::x
    real, dimension(4)::doubled_x
    
    x = (/ 1.0, 2.0, 3.0, 4.0 /)
    
    doubled_x = double_it(x)
    
    print *, doubled_x

The output would be:

   2.00000000       4.00000000       6.00000000       8.00000000

Even though my function only accepts a scalar, the elemental modifier means that it will call it for each and every array element if I pass it an array.

designer wrote:

Before this last update, for another problem, you had me change a compiler setting from Native to Generic.  I don't see that compiler setting (Native vs Generic) in the latest Apple Silcone release (Version 3.41, Build 4440).

We removed the option entirely since Apple decided to change how it reports the name of their chips, which wasn't compatible with our compiler at this time.  You shouldn't need to access that option any longer.  I believe the latest build also disables the option when creating the makefile as a safety precaution.

Jeff Armstrong
Approximatrix, LLC

Re: speed designs questions

Jeff, I looked for a description of the PURE modifier by substituting that for elemental in the URL you provided. It was an invalide URL (with pure). I then searched for pure in the Wiki and it gave a list of topics but I didn't see anything specific about "PURE" itself.

I'm excited to try this elemental feature. Could be handy. Thank you.

Re: speed designs questions

The PURE attribute is similar to the ELEMENTAL attribute in that it signifies that the function or subroutine has no side effects like changing data that wasn't passed in or generating file/screen output.  The difference is that PURE does not imply it can be used automatically on each element of an array.  Basically, an ELEMENTAL subroutine or function is also PURE but the reverse is not true.  A PURE function, for example, could accept an array as an input.

Jeff Armstrong
Approximatrix, LLC

Re: speed designs questions

So you use the word "pure" in front of the function definition?
You elemental example started: elemental function double_it(x)
So a PURE example would start: pure function double_it(x)
??

Re: speed designs questions

designer wrote:

So a PURE example would start: pure function double_it(x)

Correct!

Jeff Armstrong
Approximatrix, LLC

9 (edited by GrzegorzW 2025-12-06 09:07:20)

Re: speed designs questions

I want to add that I've never heard/used PURE/ELEMENT procedures. But I've checked 2003  (N1601.pdf) and 95 (N1191.pdf) standards and, to my surprise, they are there.