Page 1 of 2
ProcedureReturn optimisation?
Posted: Sun Jun 10, 2007 11:01 am
by PB
Which code block below is better to use, when considering final exe size and
speed of the procedure? I'd say the second is better due to far less code, but
it also creates a new variable (r), so how can I know for sure? Thanks.
Code: Select all
Procedure IsNumberLessThan100(n)
If n<100
ProcedureReturn #True
Else
ProcedureReturn #False
EndIf
EndProcedure
Debug IsNumberLessThan100(50)
Code: Select all
Procedure IsNumberLessThan100(n)
If n<100 : r=1 : EndIf
ProcedureReturn r
EndProcedure
Debug IsNumberLessThan100(50)
Posted: Sun Jun 10, 2007 11:21 am
by Trond
The first one is much faster.
This one is just as fast as the first one, but smaller:
Code: Select all
Procedure IsNumberLessThan1002(n)
If n < 100
ProcedureReturn 1
EndIf
ProcedureReturn 0
EndProcedure
Also take into account whether the majority of numbers are less than 100. If the majority is 100 or more, then this is much faster because the forward jump isn't taken:
Code: Select all
Procedure IsNumberLessThan1002(n)
If n >= 100
ProcedureReturn 0
EndIf
ProcedureReturn 1
EndProcedure
Posted: Sun Jun 10, 2007 11:24 am
by PB
Okay, the reason I asked is because I read somewhere once that a procedure
should only ever have 1 x ProcedureReturn, and I loaded one of my old sources
and saw 2 x ProcedureReturns in there, and wondered if it was worth changing
it to only one, like in my code examples in this topic. Any ideas on this?
Posted: Sun Jun 10, 2007 11:25 am
by Trond
Don't change it. Only 1 procedurereturn is only recommended for readability, it is always slower.
Posted: Sun Jun 10, 2007 11:40 am
by maw
This is how I do it:
Code: Select all
Procedure.l IsNumberLessThan100(n)
If n<100
ProcedureReturn #True
EndIf
EndProcedure
Debug IsNumberLessThan100(50)
Letting the procedure return naturally without ProcedureReturn returns #False, has worked in all versions so far, though I'm not sure this can be counted on in the future? Fred/Freak?
Not sure if it's shorter or faster, but personally I prefer it with only one ProcedureReturn.
Posted: Sun Jun 10, 2007 11:51 am
by Trond
Yes, that's shorter and faster and should be reliable for future versions as well.
Posted: Sun Jun 10, 2007 12:08 pm
by Derek
Why doesn't this work then?
Code: Select all
Procedure.l IsNumberLessThan100(n)
ProcedureReturn n<100
EndProcedure
Debug IsNumberLessThan100(50)
Debug 50<100
Debug 101<100
It does in the debug lines!
Posted: Sun Jun 10, 2007 12:18 pm
by Trond
manual
Posted: Sun Jun 10, 2007 12:47 pm
by Derek
If you mean that in the manual it says procedurereturn with a value then why doesn't this work?
Code: Select all
Procedure.l IsNumberLessThan100(n)
a=n<100
ProcedureReturn a
EndProcedure
Debug IsNumberLessThan100(50)
Debug 50<100
Debug 101<100
Also according to the manual, 'Debug - The expression can be any valid PureBasic expression, from numeric to string.'
So in the above 50<100 must be valid, therefore a=n<100 should be valid, procedurereturn a should be valid so the program should work.
I know it might be considered a boolean result and they are not implemented but in that case why does the debug command work?
Posted: Sun Jun 10, 2007 2:08 pm
by jear
Why not Macro Is()?
Code: Select all
Procedure.l IsNumberLessThan100_0(n.l)
If n<100
ProcedureReturn #True
Else
ProcedureReturn #False
EndIf
EndProcedure
Procedure.l IsNumberLessThan100_1(n.l)
If n<100 : ProcedureReturn #True : EndIf
EndProcedure
Procedure.l IsNumberLessThan100_2(n.l)
ProcedureReturn (n<100) Or #False
EndProcedure
Macro Is(expression)
expression Or #False
EndMacro
Dim num.l(1000000) : For ix.l = 0 To 999999 : num(ix) = Random(200) : Next
time.l = ElapsedMilliseconds()
For ix.l = 0 To 999999
a.l = IsNumberLessThan100_0(num(ix))
Next
Debug ElapsedMilliseconds() - time
time = ElapsedMilliseconds()
For ix = 0 To 999999
a = IsNumberLessThan100_1(num(ix))
Next
Debug ElapsedMilliseconds() - time
time = ElapsedMilliseconds()
For ix = 0 To 999999
a = IsNumberLessThan100_2(num(ix))
Next
Debug ElapsedMilliseconds() - time
time = ElapsedMilliseconds()
For ix = 0 To 999999
a = Is(num(ix) < 100)
Next
Debug ElapsedMilliseconds() - time
Posted: Sun Jun 10, 2007 2:27 pm
by Trond
I know it might be considered a boolean result and they are not implemented but in that case why does the debug command work?
Pure luck.
Posted: Sun Jun 10, 2007 2:38 pm
by Derek
Trond wrote:Pure luck.
Ah right, I thought it might be something technical like that.
Posted: Sun Jun 10, 2007 3:45 pm
by Demivec
jear wrote:Why not Macro Is()?
When you rerun your code sample without debugger and boosting the # of tests 10x you'll see the PB's first example(IsNumberLessThan100_0) is the fastest everytime. It's about twice as fast as Macro Is().
Code: Select all
Procedure.l IsNumberLessThan100_0(n.l)
If n<100
ProcedureReturn #True
Else
ProcedureReturn #False
EndIf
EndProcedure
Procedure.l IsNumberLessThan100_1(n.l)
If n<100 : ProcedureReturn #True : EndIf
EndProcedure
Procedure.l IsNumberLessThan100_2(n.l)
ProcedureReturn (n<100) Or #False
EndProcedure
Macro Is(expression)
expression Or #False
EndMacro
Dim num.l(10000000) : For IX.l = 0 To 9999999 : num(IX) = Random(200) : Next
time.l = ElapsedMilliseconds()
For IX.l = 0 To 9999999
a.l = IsNumberLessThan100_0(num(IX))
Next
b.l=ElapsedMilliseconds() - time
MessageRequester("",Str(b))
time = ElapsedMilliseconds()
For IX = 0 To 9999999
a = IsNumberLessThan100_1(num(IX))
Next
b.l=ElapsedMilliseconds() - time
MessageRequester("",Str(b))
time = ElapsedMilliseconds()
For IX = 0 To 9999999
a = IsNumberLessThan100_2(num(IX))
Next
b.l=ElapsedMilliseconds() - time
MessageRequester("",Str(b))
time = ElapsedMilliseconds()
For IX = 0 To 9999999
a = Is(num(IX) < 100)
Next
b.l=ElapsedMilliseconds() - time
MessageRequester("",Str(b))
Posted: Sun Jun 10, 2007 3:52 pm
by maw
Demivec wrote:When you rerun your code sample without debugger and boosting the # of tests 10x you'll see the PB's first example(IsNumberLessThan100_0) is the fastest everytime. It's about twice as fast as Macro Is().
Not here.. I get 110, 110, 110, 110.. And sometimes 109 or 111 on some of them..
With Core2Duo E6600, 2.4GHz, running Vista x64.
Posted: Sun Jun 10, 2007 4:08 pm
by Demivec
@maw: I'm running with an AMD athlon 64 at 2.2Ghz, running XP. Which might explain the differences. I apologize for ommiting that.
When I change the line with the test data from
Code: Select all
Dim num.l(10000000) : For IX.l = 0 To 9999999 : num(IX) = Random(200) : Next
to
Code: Select all
Dim num.l(10000000) : For IX.l = 0 To 9999999 : num(IX) = Random(99) : Next
and alternatively
Code: Select all
Dim num.l(10000000) : For IX.l = 0 To 9999999 : num(IX) = Random(200)+101 : Next
or simply put make the values all greater than 100 or all less than 100 I get a definate win for the first routine for speed in both cases.
My #'s are (125, 218, 375, 250) for the test as is.