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.