|
forums.silverfrost.com Welcome to the Silverfrost forums
|
View previous topic :: View next topic |
Author |
Message |
Kenneth_Smith
Joined: 18 May 2012 Posts: 697 Location: Hamilton, Lanarkshire, Scotland.
|
Posted: Fri Aug 25, 2017 1:15 pm Post subject: Query setting whole array to single value |
|
|
In the program below, there is a call back function line_to_gnd_cb.
Part of the calculation involves setting all the values of the complex array I_012 to the same value. I've implemented this three different ways.
Code: | do i = 1, 3
i_012(i) = v1_init/ ( sum(z) + zf )
end do |
Code: | z_local = v1_init/ ( sum(z) + zf )
i_012 = z_local |
Code: | i_012 = v1_init/ ( sum(z) + zf ) |
The third implementation causes the program to crash and I'm curious to know if this is a bug or non standard code?
Thanks
Ken |
|
Back to top |
|
|
Kenneth_Smith
Joined: 18 May 2012 Posts: 697 Location: Hamilton, Lanarkshire, Scotland.
|
Posted: Fri Aug 25, 2017 1:17 pm Post subject: |
|
|
Main code
Code: | module fault
implicit none
private
public :: build_gui
complex(kind=2) :: z(1:3)
real(kind=2) :: z1_r = 0.01d0, z1_i = 1.d0, z2_r = 0.01d0, z2_i = 1.d0, z0_r = 0.01d0, z0_i = 1.d0
complex(kind=2) :: v1_init
real(kind=2) :: v1_init_r = 1.d0, v1_init_i = 0.d0
complex(kind=2) :: zf
real(kind=2) :: zf_r = 0.d0, zf_i = 0.d0
complex(kind=2) :: i_abc(1:3), i_012(1:3), v_abc(1:3), v_012(1:3)
complex(kind=2) :: i_fault
contains
subroutine build_gui
include <windows.ins>
integer i
i = update_z_cb()
i = update_v1_init_cb()
i = update_zf_cb()
i = winio@('%ws&','Input data')
i = winio@('%nl%3.6ob&')
i = winio@('%ws&','Seq.')
i = winio@('%cb&')
i = winio@('%ws&','Re')
i = winio@('%cb&')
i = winio@('%ws&','Im')
i = winio@('%cb&')
i = winio@('%ws&','Z1 [pu]')
i = winio@('%cb&')
i = winio@('%^rf&', z1_r, update_z_cb)
i = winio@('%cb&')
i = winio@('%^rf&', z1_i, update_z_cb)
i = winio@('%cb&')
i = winio@('%ws&','Z2 [pu]')
i = winio@('%cb&')
i = winio@('%^rf&', z2_r, update_z_cb)
i = winio@('%cb&')
i = winio@('%^rf&', z2_i, update_z_cb)
i = winio@('%cb&')
i = winio@('%ws&','Z0 [pu]')
i = winio@('%cb&')
i = winio@('%^rf&', z0_r, update_z_cb)
i = winio@('%cb&')
i = winio@('%^rf&', z0_i, update_z_cb)
i = winio@('%cb&')
i = winio@('%ws&','V1 [pu]')
i = winio@('%cb&')
i = winio@('%^rf&', v1_init_r, update_v1_init_cb)
i = winio@('%cb&')
i = winio@('%^rf&', v1_init_i, update_v1_init_cb)
i = winio@('%cb&')
i = winio@('%ws&','Zf [pu]')
i = winio@('%cb&')
i = winio@('%^rf&', zf_r, update_zf_cb)
i = winio@('%cb&')
i = winio@('%^rf&', zf_i, update_zf_cb)
i = winio@('%cb&')
i = winio@('%nl%^tt[L to G]',line_to_gnd_cb)
end subroutine build_gui
integer function update_z_cb()
z(1) = cmplx(z0_r,z0_i)
z(2) = cmplx(z1_r,z1_i)
z(3) = cmplx(z2_r,z2_i)
update_z_cb=1
end function update_z_cb
integer function update_v1_init_cb()
v1_init = cmplx(v1_init_r,v1_init_i)
update_v1_init_cb = 1
end function update_v1_init_cb
integer function update_zf_cb()
zf = cmplx(zf_r, zf_i)
update_zf_cb = 1
end function update_zf_cb
integer function line_to_gnd_cb()
integer i
complex(kind=2) z_local
! This works:-
do i = 1, 3
i_012(i) = v1_init/ ( sum(z) + zf )
end do
! This works:-
! z_local = v1_init/ ( sum(z) + zf )
! i_012 = z_local
! This does not work:-
! i_012 = v1_init/ ( sum(z) + zf )
i_fault = sum(i_012)
write(6,*) abs(i_fault)
line_to_gnd_cb = 1
end function line_to_gnd_cb
end module fault
program fault_analysis
use fault
implicit none
call build_gui
end program fault_analysis |
|
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7932 Location: Salford, UK
|
Posted: Fri Aug 25, 2017 9:35 pm Post subject: |
|
|
At first sight the code looks OK so the compiler has probably failed to implement the code correctly. The different approaches are roughly equivalent and each one calculates sum(z) three times when once would be enough.
If you were to calculate and save sum(z) first, then you would probably be OK either way. |
|
Back to top |
|
|
Kenneth_Smith
Joined: 18 May 2012 Posts: 697 Location: Hamilton, Lanarkshire, Scotland.
|
Posted: Fri Aug 25, 2017 10:42 pm Post subject: |
|
|
Thanks Paul,
Interesting to know that the 3rd method actually calculates the SUM term three times - I had not appreciated that. And the third method was the one I implemented first - caught out trying to do some quick and dirty coding - again
Ken |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7932 Location: Salford, UK
|
Posted: Sat Aug 26, 2017 7:12 am Post subject: |
|
|
This turns out to be a bug relating to COMPLEX arrays and SUM. I have made a note that it needs fixing.
Here is a cut down demonstration...
Code: | integer,parameter::k=2
complex(kind=k) :: zz(1:3),z(1:3)
z = 1.0d0
zz = sum(z)
print*, zz
end
|
|
|
Back to top |
|
|
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2390 Location: Yateley, Hants, UK
|
Posted: Sat Aug 26, 2017 12:30 pm Post subject: |
|
|
I found it interesting, but unsurprising, that SUM(Z) is computed three times. Presumably it is only calculated once if /OPTIMISE is used, because (from FTN95.CHM) there is:
"Loop invariant motion. This means that any calculations which are constant with respect to the loop variable may be moved, so that they are performed once and for all on entry to the loop."
"Elimination of common subexpressions across statements."
My questions are 'Does the right hand side (in this case) count as a common subexpression?', 'Is an assignment of an expression to an array an implicit loop?' and 'Does including a function like SUM inhibit the optimisation?'
Notwithstanding the advice that manual precalculation of common subexpressions is unnecessary, I have always done it when I have recognised the case. Hence, where FTN95.CHM states:
"In most cases, common sub-expressions are evaluated only once. Thus the following code could not be improved by the prior assignment TEMP=X*Y:
Z = (X*Y)/(1.0+X*Y)"
I would probably precalculate X*Y out of force of habit (on the advice of Kreitzberg & Schneiderman, 1972, which predates a lot of optimising compilers). Paul's suggestion of precalculation goes against the FTN95.CHM advice, but would be rational if the advice on common subexpressions in FTN95.CHM observed that the process is hampered if functions are involved - again, I think it is fair to say that it should be possible to work out which are safe and which are not, so RANDOM@ is clearly not safe, SUM ought to be.
I can't imagine that one feels the benefit of summing three variables once instead of three times, but in the general case, my habit is likely to prove advantageous, and only very slightly worse than achieved by the optimiser. Or am I wrong?
As a postscript, it seems to me that common subexpression replacement is so obvious and side-effect free that perhaps it should be done as a matter of course and not just when /OPT is used?
Eddie |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7932 Location: Salford, UK
|
Posted: Mon Aug 28, 2017 8:24 am Post subject: |
|
|
The above cut-down demo program also fails when /opt is applied so evidently SUM is not optimised (at least in this situation).
The documentation states that calculations "may" be removed. This is not guaranteed.
As to what counts as a common subexpression, I don't have any further information above that found in the documentation but here are some of my random thoughts on optimisation.
1) It is rarely an issue that one needs to be concerned about.
2) Run times are not just dependent on code efficiency (amount of RAM, type of video driver, antivirus software, connection to the Internet, type and speed of the CPU).
3) Personally I aim to write efficient code and to avoid depending on the optimiser but this is, more often than not, a matter of professional pride; but it does tend to make the code easier to read and maintain.
4) When the speed of execution becomes critical...
a) FTN95 has a /TIMING option that provides information on the CPU time spent in each subroutine (so you can see where best to focus on optimising the code).
b) The next release of 64 bit FTN95 will have a /PROFILE option that reports how many times each line is executed (again to show where best to optimise).
c) The FTN95 option /EXPLIST provides the assembler code so you can work out how the compiler has translated your code. If you are really desperate you can write sections of the code in assembler.
I hope that this helps without raising further questions. |
|
Back to top |
|
|
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2390 Location: Yateley, Hants, UK
|
Posted: Mon Aug 28, 2017 8:46 am Post subject: |
|
|
Paul,
That's an excellent explanation, for which I am grateful.
Eddie |
|
Back to top |
|
|
John-Silver
Joined: 30 Jul 2013 Posts: 1520 Location: Aerospace Valley
|
Posted: Mon Aug 28, 2017 10:40 pm Post subject: |
|
|
The best optimiser is the idiot on the end of the keyboard.
Simply becasue he knows what he has done ! |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7932 Location: Salford, UK
|
Posted: Wed Mar 20, 2019 9:23 pm Post subject: |
|
|
Ftn95 has been fixed for the next release so that the cut down program above now runs correctly. |
|
Back to top |
|
|
John-Silver
Joined: 30 Jul 2013 Posts: 1520 Location: Aerospace Valley
|
Posted: Wed Mar 20, 2019 11:10 pm Post subject: |
|
|
... and Ken's non-cutdown code runs ok ? _________________ ''Computers (HAL and MARVIN excepted) are incredibly rigid. They question nothing. Especially input data.Human beings are incredibly trusting of computers and don't check input data. Together cocking up even the simplest calculation ... " |
|
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
|