Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Code style question: Multiplication vs. powers of 2 or 3

qolin
Novice
1,727 Views

I have a colleague who insists on writing code such as this :

!-----calculate Grashof numbers --------------

grashm = G * betam * dt * (L*L*L) * (denm*denm) / (vism*vism) ! fluid mean

grashl = G * betal * dt * (L*L*L) * (denl*denl) / (visl*visl) ! liquid

grashg = G * betag * dt * (L*L*L) * (deng*deng) / (visg*visg) ! gas

 Compared to my usual practice, which would be this:

grashm = G * betam * dt * L**3 * denm**2 / vism**2 ! fluid mean

grashl = G * betal * dt * L**3 * denl**2 / visl**2 ! liquid

grashg = G * betag * dt * L**3 * deng**2 / visg**2 ! gas

What are the pros and cons here? Is there any chance one or the other of these will be faster in execution, assuming they are both compiled with full optimization?

Qolin

0 Kudos
1 Solution
Steven_L_Intel1
Employee
1,727 Views

Yes - I prescribe a whack on the fingers with a coding ruler. I'd argue that the compiler will have an easier time optimizing (L**3) than it would (L*L*L).

View solution in original post

0 Kudos
16 Replies
TimP
Honored Contributor III
1,727 Views
If you have a specific compiler and option set in mind you might compare generated code. For example does ifort ignoring parens show defincies or do you employ a substandard c translation.
0 Kudos
rase
New Contributor I
1,727 Views

I prefer the multiplication over the "**" (power to) sign. You can even omit the parantheses preceding the division character (/) which facilitates the analysis for the compiler. I have no factual evidence that the multiplication is faster. The reason I use the multiplication is that I was was taught about a hundred years ago ;-) to avoid terms with ** whenever possible. That may had been valid with the computers and compilers available at those days. Maybe more recent compilers are able to recognize and convert exponentiation into a sequence of multiplications. Could the gurus more familiar with the code analysis and optimization of IVF comment on the subject?

0 Kudos
Steven_L_Intel1
Employee
1,727 Views

The compiler recognizes idioms such as **2 and **3 and generates the most efficient code for it. I recommend using the syntax that is clearest for the human reader.

0 Kudos
FortranFan
Honored Contributor III
1,727 Views

qolin wrote:

I have a colleague who insists on writing code such as this :

!-----calculate Grashof numbers --------------

grashm = G * betam * dt * (L*L*L) * (denm*denm) / (vism*vism) ! fluid mean

...

You need to send your colleague to Dr Fortran's clinic, PRONTO !!! :-))

0 Kudos
Steven_L_Intel1
Employee
1,728 Views

Yes - I prescribe a whack on the fingers with a coding ruler. I'd argue that the compiler will have an easier time optimizing (L**3) than it would (L*L*L).

0 Kudos
John_Campbell
New Contributor II
1,727 Views

What about:

grashm = G * betam * dt * L*  (L * denm / vism)**2 ! fluid mean

Unless this code impacts significantly on performance, my recommendation is to write the code in a layout that looks like how the calculation is documented, rather than what is might be optimal. That way it is easier to check what has been coded and the compiler will probably optimise what you code anyway.

John

0 Kudos
Craig_Dedo
New Contributor I
1,727 Views

I strongly agree with Steve Lionel and John Campbell.  From the very beginning, i.e., 1975, I have had an instinct to optimize human readability and understandability over competing interests.  During my undergraduate studies, I clearly remember my professors in both my computer science and engineering classes recommending a series of multiplications in place of exponentiation to an integer power.  I thought about this and decided back then to use exponentiation because it made the source code clearer.

I have followed this principle ever since.  So far, I have not run into a situation where writing the most clear, straightforward source code did not produce high quality results.  In my experience, the most precious resource, i.e., the resource in the shortest supply, has always been human effort.  Writing the most clear, straightforward source code has optimized the number of direct labor hours (DLH) involved in subsequent improvements.

Today's Fortran compilers, both IVF and the competition, use such advanced compiler and optimization technology that such attempts are likely to produce zero or only a negligible improvement.  Unless you are writing monster applications that stress the limits of the hardware, you are well advised to write clear, correct source code that is easy on the human reader.

This issue brings to mind the adage, "Premature optimization is the root of many evils."  I have encountered this principle in real-life software development many times.  There are two rules of thumb that have proven themselves over and over again:

1.  Don't optimize yet.

2.  Don't optimize until you really have to.

Steve McConnell, the author of Code Complete:  A Practical Handbook of Software Construction, emphasize this approach in both editions of his book.  In the second edition, they are in Chapter 25, "Code-Tuning Strategies", and Chapter 34, "Themes in Software Craftsmanship".  I strongly recommend that all persons especially read Section 34.3, "Write Programs for People First, Computers Second".

0 Kudos
DavidWhite
Valued Contributor II
1,727 Views

Steve,

Regarding your comment "The compiler recognizes idioms such as **2 and **3 and generates the most efficient code for it. I recommend using the syntax that is clearest for the human reader." does this apply to higher powers?

For polynomial evaluation, does this mean we should eliminate all the nested *x terms?

Thanks,

David

0 Kudos
TimP
Honored Contributor III
1,727 Views

For evaluation of a polynomial, grouping of terms to reduce total number of multiplications may be preferred, somewhat toward Horner style evaluation e.g.  x + x**3*(a + b*x**2)

on the off chance this may bear on what you meant.  The compiler is likely to recognize some common factors among exponentiations but not to optimize association of additions.

0 Kudos
Steven_L_Intel1
Employee
1,727 Views

David, I am not sure how high a power the compiler recognizes as an idiom. I started to test this but got bored when it was still recognizing a power of 15. The power can even be a real value as long as it is a constant that is integer valued, such as 3.0.

For example, this is what I get for x**15:

        movss     xmm1, DWORD PTR [eax]                         ;3.5
        movaps    xmm0, xmm1                                    ;3.5
        mulss     xmm0, xmm1                                    ;3.5
        movaps    xmm2, xmm0                                    ;3.5
        mulss     xmm2, xmm0                                    ;3.5
        mulss     xmm1, xmm0                                    ;3.5
        movaps    xmm3, xmm2                                    ;3.5
        mulss     xmm3, xmm2                                    ;3.5
        mulss     xmm2, xmm1                                    ;3.5
        mulss     xmm3, xmm2                                    ;3.5

 

DavidWhite
Valued Contributor II
1,727 Views

Thanks, Steve.

I was really only thinking in the range up to about x**6, so x**15 is far beyond anything I would normally encounter, except for the NIST Steam Properties, which have powers up to +32 and -41.

For many years, I have used expansions like         a + x*(b + x*(c + x*d))

but obviously this is not needed.

Regards,

David

0 Kudos
mecej4
Honored Contributor III
1,727 Views

David White wrote:
For many years, I have used expansions like         a + x*(b + x*(c + x*d))

Many years ago, some compilers that ran on the IBM PC used to produce code for a + x*(b + x*(c + x*(d + x*e))) that would cause overflow of the x87 stack, whereas the rearranged but equivalent form (((x*e + d)*x + c)*x + b)*x + a did not lead to such a problem.

John_Campbell
New Contributor II
1,727 Views

mecej4,

All those coding tricks we are forgetting and becoming lazy !!
Managing virtual memory has remained relevant, which might explain why our real memory hasn't.

John

 

0 Kudos
FortranFan
Honored Contributor III
1,727 Views

John Campbell wrote:

...

All those coding tricks we are forgetting and becoming lazy !!

..

Didn't Craig Dedo and Dr Fortran explain the "coding tricks" produce suboptimal code more often not and coders are better off without them; young ones better never learn them and experienced ones should eradicate them no sooner than polio.

0 Kudos
TimP
Honored Contributor III
1,727 Views

I don't agree about writing polynomials in optimum fashion being a suboptimal coding trick.  You could argue that it was more important prior to availability of IEEE754 hardware, but it still promotes accuracy and avoidance of over and underflow.  

The Fortran rules about alternative evaluation of arithmetic expressions have been repeated without change in each new version of the standard, which I take as expert confirmation that such basics were done right the first time.

0 Kudos
dboggs
New Contributor I
1,727 Views

Sometimes I think my life would be better after a visit from the Men In Black with their fancy flashlight. Well, maybe not. No wait--I can't remember.

0 Kudos
Reply