|
forums.silverfrost.com Welcome to the Silverfrost forums
|
View previous topic :: View next topic |
Author |
Message |
mecej4
Joined: 31 Oct 2006 Posts: 1897
|
Posted: Thu Oct 20, 2022 1:26 am Post subject: Detecting and warning about fake DO loops |
|
|
One of the Fortran benchmark codes that DanRRight wrote about recently contains two code segments with the following pattern:
Code: | !CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
!
! ITERATION SCHEME FOR CIRCULATION (GAM)
!
!CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
!
DO j = 2 , N - 1
IF ( ABS((g_new(j) - g_old(j))/g_new(j)) .GT. g_tol ) GOTO 70
GOTO 80
ENDDO
...
70 <replace g_old by g_new and continue iterations unless iteration limit has been reached>
...
80 <iterative process has converged. Proceed with next part of calculation> |
It took me a while to recognise that the body of the DO loop can only be executed zero or one times! If N < 3, the loop is not executed at all. Otherwise, the IF condition is tested. Regardless of the result of the test, the loop is exited (to 70 if TRUE, to 80 if FALSE). I could replace the DO .. line by "j = 2" and remove the ENDDO line, and the program would behave the same as it does now.
If it is not too much trouble to implement, it would be nice to have the compiler detect this pattern and issue a warning that this is a not a normal DO loop.
The fake DO loop hides what I think is a major error in the program. What the original programmer meant (and wrote in old Fortran 77 style) was
Code: | IF (ANY (ABS((g_new - g_old)/g_new) .GT. g_tol) ) THEN
GO TO 70 ! continue iterations
ELSE
GOTO 80 ! iterations have converged; proceed to next part
ENDIF |
I suspect that the GOTO 80 should have come after the ENDDO, but got misplaced by a code polisher/reformatter.
Why do I have that suspicion? Normally, when solving a set of simultaneous equations (linear or nonlinear) by an iterative method, the algorithm is along the lines of
Code: | g = g_old # use old array g_old as the trial solution for the fixed point iteration g = F(g)
iter := 0;
do
iter := iter+1; if (iter >= max_iter) exit B # failed to converge
g_new := F(g)
delta := ||g_new-g_|| # norm of change in array g
if (delta <= g_tol) exit A # converged
g := g + \omega * (g_new - g) # \omega is the relaxation parameter
end do |
|
|
Back to top |
|
|
DanRRight
Joined: 10 Mar 2008 Posts: 2877 Location: South Pole, Antarctica
|
Posted: Thu Oct 20, 2022 9:16 am Post subject: |
|
|
Devilry. This may be because the original author liked "GOTO 666" i counted more than 50 times in his code. ROTFL! Self-fulfilled prophecy.
Want to look at original code? I can send it. Or you can get it from his website. ZIP file contains EXE files though, be careful, do not run them
So the FTN95 executed and executed the DO loop while all other compilers just ignored it like it should be ? Or the opposite, FTN95 was doing everything right and all other compilers cheated ?
Nice catch if this is indeed the case. |
|
Back to top |
|
|
mecej4
Joined: 31 Oct 2006 Posts: 1897
|
Posted: Thu Oct 20, 2022 2:12 pm Post subject: |
|
|
The mp_prop_design program is unfit to be used as a benchmark.
If you search through the history of the PB11 benchmarks, you may notice that the suite did not include mp_prop_design before 2011. Its original author (Anthony Falzone, an engineer) admits in his Bugzilla thread ( https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53957 ) that "I am not much of a programmer". He has also stated his opinion regarding the program being used as a benchmark at https://propdesign.jimdofree.com/notes/ ; scroll down to the "Benchmarking" section on that page.
The Fortran source code is quite inefficient, with many expressions being repeatedly evaluated inside long DO loops when portions or even whole expressions could be calculated and stored into temporary scalar variables before entering the loop. Here is an example:
Code: | DO j = 1 , tip
chord(j) = SQRT(((radius/rocr)**2.0)*(1.0-((((REAL(j) - 1.0) &
& /(REAL(tip)-1.0))*radius)**2.0/radius**2.0)))
ENDDO |
could be simplified to
Code: | f = radius/rocr
DO j = 1 , tip
chord(j) = f*sqrt((tip - j)/(tip - 1.0D0))
ENDDO |
Compared to other compilers, FTN95 does not attempt to do massive amounts of loop optimisation. Therefore, the code that it produces, even with /64 /opt, requires 13 SSE2 arithmetic operations per loop for the first version, instead of just 4 for the second version. Notice, too, that the original author writes "radius**2.0" instead of "radius**2" or "radius*radius". Most current Fortran compilers, including FTN95, avoid the trap of calling LOG() and EXP() functions because of the exponent being REAL instead of INTEGER.
A second example:
Code: | dwtx = (dgame(k)/(4.0D0*PI)) &
& *((dlty*distz-dltz*disty) &
& /(SQRT(ABS(distx)**2.0D0+ABS(disty) &
& **2.0D0+ABS(distz)**2.0D0))**3.0D0) |
Why apply ABS when you are going to square the argument?
A third example:
Code: | delta(j) = ACOS(dr(j)/dl(j))
arg1 = pitch
arg2 = 2.0D0*PI*r(j)*COS(delta(j)) |
Two statements after he applied ACOS, he applies COS to the result. There is a price to be paid for such programming practices.
--- --- ---
I did look at Falzone's downloadable zip file at https://propdesign.jimdofree.com/ . The closest Fortran source in that to the mp_prop_design.f90 code is PROP_DESIGN_MAPS.f, but this is substantially different, not only in the program code but also the input data files used. Both programs contain a few minor bugs that FTN95 catches.
Finally, both mp_prop_design.f90 and PROP_DESIGN_MAPS.f perform large amounts of I/O, to the screen as well as to result files. As a result, if we use them as benchmarks, are we benchmarking for CPU speed, compiler output quality, or I/O hardware throughput?
Last edited by mecej4 on Sat Oct 22, 2022 11:54 am; edited 2 times in total |
|
Back to top |
|
|
JohnCampbell
Joined: 16 Feb 2006 Posts: 2593 Location: Sydney
|
Posted: Fri Oct 21, 2022 2:50 am Post subject: |
|
|
Most of the PB11 programs are VERY poorly written, with little attention to using "efficient" coding approaches. Even Engineers who wrote Fortran can understand efficiency.
In these PB11 codes, there are many examples of replicated computation in DO loops and calculations that could be moved outside the DO for efficiency.
What do you do for someone that writes "((radius/rocr)**2.0)" ? In older implementations of FORTRAN, the performance hit would have been worse !
So why are these programs targeted at optimisation if the authors did not care ? Unfortunately ifort and other compilers have included optimisation that target these examples, probably at the expense of what other codes require !
The three main areas where FTN95 is/was less efficient are :
1) optimisation in DO loops to remove repeated or loop independent calculations.
2) use of temporary arrays for array sections.
3) use of AVX vector instructions, especially for inner loops.
When efficiency is being targeted, it is mostly the inner loops that are most important. For my FE calculations, AVX functions are easily included, but for more complex field theory calculations, use of AVX instructions can be more complex.
Fortunately, the area where FTN95 is more effective is in diagnostics, so it remains a very useful Fortran tool. |
|
Back to top |
|
|
DanRRight
Joined: 10 Mar 2008 Posts: 2877 Location: South Pole, Antarctica
|
Posted: Fri Oct 21, 2022 10:25 pm Post subject: |
|
|
Great, Mecej4 and John. Interesting findings. Decently, i was shocked, about what will tell you later. So GOTO 70 and GOTO 80 place is not the reason? Also I doubt print to the screen is slowing by more than a percent. Please keep investigating.
Motto came to my mind: "FTN95 : the compiler for real pros".
And another: "Real programmers do not use compiler optimization, they optimize codes by hand"
Now i understand why FTN95 is the only compiler where you can mix fortran and assembler source text in the same subroutine and Fortran compiler will swallow that as its own. |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8040 Location: Salford, UK
|
Posted: Sat Oct 22, 2022 9:52 am Post subject: |
|
|
mecej4
I have seen your comment Quote: | If it is not too much trouble to implement, it would be nice to have the compiler detect this pattern and issue a warning that this is a not a normal DO loop. | .
Do you have any suggestions as to what the compiler should look for? |
|
Back to top |
|
|
mecej4
Joined: 31 Oct 2006 Posts: 1897
|
Posted: Sat Oct 22, 2022 10:05 am Post subject: |
|
|
Here is what I think should suffice:
1. Do loop body contains several IF statements or IF..THEN..ELSE...ENDIF structures.
2. Every one of these alternative paths within the DO loop contains an EXIT statement or a GOTO statement, and every one of those GOTO statements has a target statement number that is located outside the DO loop.
[Note: I am presuming that we rarely see instances of the old Fortran "extended DO range", where one could GOTO from inside the DO loop to the outside, execute some statements, followed by another GOTO back to a statement number within the DO loop.] |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8040 Location: Salford, UK
|
Posted: Thu Nov 17, 2022 3:46 pm Post subject: |
|
|
mecej4
I have had a look at this and I don't think that it can be done within a reasonable time frame. |
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|