forums.silverfrost.com Forum Index forums.silverfrost.com
Welcome to the Silverfrost forums
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Query setting whole array to single value

 
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> Support
View previous topic :: View next topic  
Author Message
Kenneth_Smith



Joined: 18 May 2012
Posts: 126
Location: Glasgow, Scotland.

PostPosted: Fri Aug 25, 2017 1:15 pm    Post subject: Query setting whole array to single value Reply with quote

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
View user's profile Send private message Visit poster's website
Kenneth_Smith



Joined: 18 May 2012
Posts: 126
Location: Glasgow, Scotland.

PostPosted: Fri Aug 25, 2017 1:17 pm    Post subject: Reply with quote

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
View user's profile Send private message Visit poster's website
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 4919
Location: Salford, UK

PostPosted: Fri Aug 25, 2017 9:35 pm    Post subject: Reply with quote

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
View user's profile Send private message
Kenneth_Smith



Joined: 18 May 2012
Posts: 126
Location: Glasgow, Scotland.

PostPosted: Fri Aug 25, 2017 10:42 pm    Post subject: Reply with quote

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 Evil or Very Mad

Ken
Back to top
View user's profile Send private message Visit poster's website
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 4919
Location: Salford, UK

PostPosted: Sat Aug 26, 2017 7:12 am    Post subject: Reply with quote

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
View user's profile Send private message
LitusSaxonicum



Joined: 23 Aug 2005
Posts: 1652
Location: Yateley, Hants, UK

PostPosted: Sat Aug 26, 2017 12:30 pm    Post subject: Reply with quote

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
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 4919
Location: Salford, UK

PostPosted: Mon Aug 28, 2017 8:24 am    Post subject: Reply with quote

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
View user's profile Send private message
LitusSaxonicum



Joined: 23 Aug 2005
Posts: 1652
Location: Yateley, Hants, UK

PostPosted: Mon Aug 28, 2017 8:46 am    Post subject: Reply with quote

Paul,

That's an excellent explanation, for which I am grateful.

Eddie
Back to top
View user's profile Send private message
John-Silver



Joined: 30 Jul 2013
Posts: 558

PostPosted: Mon Aug 28, 2017 10:40 pm    Post subject: Reply with quote

The best optimiser is the idiot on the end of the keyboard.
Simply becasue he knows what he has done !
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> Support All times are GMT + 1 Hour
Page 1 of 1

 
Jump to:  
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