Silverfrost Forums

Welcome to our forums

Time

19 Nov 2012 3:45 #11090

Hi there,

I have some code that is called millions of times in succession, and naturally I want it to be as fast as possible. However, I have noticed something that is both cough interesting but above all very frustrating.

I have a file that contains structures thus:

Module Animal_hdr

Type stColours Integer*1, Pointer i1Colour(:) End Type stColours

Type stStripes Type(stColours), Pointer :: pstStripe(:, 😃 EndType stStripes

Type stZebras Type(stStripes), Pointer :: pstZebra(:, 😃 Integer*4 :: iOffsetLargeX, iOffsetLargeY EndType stZebras

End Module Animal_hdr

Now, the routine that is called millions of times has the following (and more) lines in it:

!! Passed Type(stZebras), INTENT(INOUT) :: pstZebraP

!! Locals Type(stStripes), Pointer :: ptrZebraL Type(stColours), Pointer :: ptrStripeL

ptrZebraL => pstZebraP%pstZebra(iyOffsetL + 1, ixOffsetL + 1)
ptrStripeL => ptrZebraL%pstStripe(iySmallIxL + 1, ixSmallIxL + 1)

and it takes around 124 seconds on my 520M Laptop to exectute 1M times.

However, if I change the above two lines for the single line:

ptrStripeL => pstZebraP%pstZebra(iyOffsetL + 1, ixOffsetL + 1) &

& %pstStripe(iySmallIxL + 1, ixSmallIxL + 1)

then it takes around 10 seconds to execute.

Not only that, if I try the trick in another place of this routine it actually slows things down, and so even though it is a mystery, I can't even follow a rule-of-thumb to get me by right now.

Any help much appreciated.

Marz

PS: I have written a small stand-alone project for the above.

19 Nov 2012 8:25 #11093

Use /explist on the command line to look at the assembler code for these statements. Then use /opt to see if you can get better times.

19 Nov 2012 3:22 #11099

Now then, I used /EXPLIST and found the following:

Single-line pointing has 414 lines of code generated for it Two-line pointing has 114 lines of code generated for it

The first 113 lines match exactly.

For two-line pointing:

  1. many TEMP@XX (assume memory usage) are used
  2. pointer-checking via __PCHECK is used

None of them are found in the single-line pointing assembly language for the line in question.

I assume then that the massive delays are due to

  1. Memory access overhead compared to register usage
  2. Pointer checking overhead

I shall attempt to research how to turn off Pointer-checking, assuming it is via !FTN95$OPTIONS(*) and/or compiler options in the IDE.

__intermediate_interrupt@ is called in both, but, as yet, have no idea what it does.

Marz

19 Nov 2012 3:34 #11100

Are you using /CHECK? If so then this is only intended for development and can be switched off for production runs. Alternatively you might switch it off locally.

19 Nov 2012 3:58 (Edited: 19 Nov 2012 5:03) #11101

Aha! That'll be the beauty. I turned off everything apart from /DEBUG and, the two-pointer code ran in less than 1 second ðŸ˜Ū)

Thanks for that.

Marz

19 Nov 2012 4:39 #11103

how about removing the /debug too?

19 Nov 2012 5:03 #11104

That would mean outputting the timings to a file or timing it with a stopwatch and I'm in no mood to do either ðŸ˜Ūp

As far as I'm concerned my issue has been addressed. I am still surprised that such a simple change to a program can have such a dramatic impact. Slowing down that code by a factor of 12 appeared to be pure insanity at the time ðŸ˜Ū)

Marz

19 Nov 2012 5:37 #11106

Well, debugging is one of the most powerhungry options, measuring speed with it has no sense.

19 Nov 2012 5:50 #11107

Hmmm, but I'm not interested in the absolute time that it takes - I am really only interested in the relative timings between the 1-line and the 2-line versions of the code. The only reason I began timing them in the first place was in order to get a measure of what was going on and for helping with the posts here.

Marz

Please login to reply.