Announcement

Collapse
No announcement yet.

Optimization For Speed -- Any Thoughts?

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Optimization For Speed -- Any Thoughts?

    I have a relatively small function, which my profiler has indicated is taking a majority of the time and was hoping to optimize it some. Looking over some of the recent posts, I have been able to make some progress but would like to see if this can be sped up any more. What the function does is extract the value of two bits from a passed in byte. The code as it is now is:

    Code:
    Private Function Extract_TWO_Bits(TheBYTE As Byte, Position As Integer) As Integer
    
    
    	On Position GoTo Zero, Two, Four, Six
                         
    	Zero:
    	    '// Isolates BITS 0 and 1
    	    Extract_TWO_Bits = (TheBYTE And 3)          '// 3 = &H3
    	    Exit Function
                         
    	Two:
    	    '// Isolates BITS 2 and 3
    	    Extract_TWO_Bits = (TheBYTE And 12) \ 4    '// 12 = &HC
    	    Exit Function
                        
    	Four:
    	    '// Isolates BITS 4 and 5
    	    Extract_TWO_Bits = (TheBYTE And 48) \ 16     '// 48 = &H30
    	    Exit Function
                         
    	Six:
    	    '// Isolates BITS 6 and 7
    	    Extract_TWO_Bits = TheBYTE \ 64
    	    Exit Function
    
    End Function
    Changing from a SELECT CASE to the On ... GoTo made a big improvement. From looking at this code is there anything else I can do to make this faster?

    Also, in another function (which now takes most of the time), the two lines consuming most clock cycles are:

    Code:
                INTPortion = Int(RAWPrice / 100#)
                DECPortion = ((RAWPrice / 100#) - INTPortion) * 100#
    Is there any way to speed these up at all?

    I am looking forward dot your responses. Many thanks in advance.

    Best regards,

    Andrew Peskin
    [email protected]


    ------------------


    [This message has been edited by Andrew Peskin (edited March 21, 2001).]

  • #2
    Andrew,

    Use an integer divide:
    IntPortion = RawPrice \ 100
    And a Mod
    DecPortion = (RawPrice mod 100) * 100

    ------------------
    "There are two novels that can change a bookish fourteen-year old's life: The Lord of the Rings and Atlas Shrugged. One is a childish fantasy that often engenders a lifelong obsession with its unbelievable heroes, leading to an emotionally stunted, socially crippled adulthood, unable to deal with the real world. The other, of course, involves orcs." - John Rogers

    Comment


    • #3
      Andrew,

      #1) Have you tried using SHIFT RIGHT instead of \ ? I don't know
      if it is faster or not, but you might try testing it.

      #2) INTPortion = FIX( RAWPrice) ?
      DECPortion = FRAC( RAWPrice) ?



      ------------------
      Bernard Ertl
      Bernard Ertl
      InterPlan Systems

      Comment


      • #4
        On the lines of Bern's suggestion this gets rid of the Goto's ..
        it might be faster

        Replace the all the code with

        ' shifts the desired bits to bits 0,1 .. mask off other bits
        Function = SHIFT RIGHT TheByte, (position*2)-2) AND &H03

        I am not sure of the syntax but that is the idea.

        Mike

        ------------------

        Comment


        • #5
          Good idea Mike, after that you can forget about calling a FUNCTION and just put that line whereever it's needed.
          That way you'd eliminate the function calling overhead.

          I was going to suggest using only LONGs, also as parameters but there's no need if you can eliminate the function altogether.


          Peter.


          ------------------
          [email protected]
          [email protected]

          Comment


          • #6
            Originally posted by Mike Burns:
            On the lines of Bern's suggestion this gets rid of the Goto's ..
            it might be faster

            Replace the all the code with

            ' shifts the desired bits to bits 0,1 .. mask off other bits
            Function = SHIFT RIGHT TheByte, (position*2)-2) AND &H03

            I am not sure of the syntax but that is the idea.

            Mike
            What would the sytax be for this? Would it be able to extract the 2 specific bits you wanted based on position? Anyone know how to write this?

            Andrew



            ------------------

            Comment


            • #7
              Hi Andrew!

              Sorry I don't have any advice to offer you on this, but I'm interested
              in knowing what your "profiler" app is. What is the name of it? Is it
              a part of PB? Thanks in advance!

              Regards,
              Scott


              ------------------
              Scott Wolfington
              http://www.boogietools.com


              [This message has been edited by Scott Wolfington (edited March 05, 2003).]
              Scott Wolfington
              [url="http://www.boogietools.com"]http://www.boogietools.com[/url]

              Comment


              • #8
                Here is another line which is reported to take 76 Clock Ticks, is there any way to speed it up?

                FUNCTION = ((RAWPrice& / (10& ^ ConvFact&)) / MinTick#)

                Anyone have any ideas on this?

                Many thanks.

                Andrew

                ------------------

                Comment


                • #9
                  Originally posted by Scott Wolfington:
                  Hi Andrew!

                  Sorry I don't have any advice to offer you on this, but I'm interested
                  in knowing what your "profiler" app is. What is the name of it? Is it
                  a part of PB? Thanks in advance!

                  Regards,
                  Scott

                  I use a multi-step process for trying to benchmark/analyze code I write to determine where the bottlenecks are. I first have a simple procedure that I can place at the beginning and ending of each function call which logs time spent in each. Once certain functions are flagged as taking the most time, I compile the application (or a subset of it) in Visual Basic creating a Symbolic Debug File (I rarely have to make minor modifications and usually have no problems cross compiling my code). I then use Intel's VTune performance analyzer to profile the application. I realize that VB and PB are drastically different compilers, but after first using the information in the output log from running the PB app, I can then more precisely hone in on the problem areas with VTune in the VB app. Usually once I make changes and get performance increases on the specific lines it flags, I do see an improvement in my PB application. I realize that this is sort of a long way around approach, but it works pretty nicely for me.

                  Hope this was helpful. If you are interested, Email me directly for more information.

                  Andrew



                  ------------------

                  Comment


                  • #10
                    Andrew,

                    Since SHIFT is a statement and it appears to destroy (alter)
                    the operand you might need to

                    A) Pass TheByte BYVAL (I think that will pass a copy of TheByte)
                    and
                    B) Use 2 lines in the function

                    Code:
                    Function Extract_Two_Bits(BYVAL TheByte As Byte, position as Integer) as Integer
                        SHIFT RIGHT TheByte, (Position*2)-2
                        Function = TheByte AND &H03
                    End Function
                    Based upon position, this will move the two bits you want
                    to bits 0,1 .. then mask off the remaining bits.

                    Mike


                    ------------------

                    Comment


                    • #11
                      Andrew, SHIFT is a statement (SUB). You will need to create a function
                      to use it (BTW, Peter is right, convert to LONGS if possible).

                      Code:
                      'Added BYVAL so I can modify the parameters
                      Private Function Extract_TWO_Bits(BYVAL TheBYTE As Byte, BYVAL Position As Integer) As Integer
                      
                         'Assumes Position = 0,2,4,6
                         SHIFT RIGHT TheBYTE, Position
                         FUNCTION = TheBYTE AND &H03
                      
                      END FUNCTION
                      Hey Mike! We posted at the same time!


                      ------------------
                      Bernard Ertl

                      [This message has been edited by Bern Ertl (edited March 21, 2001).]
                      Bernard Ertl
                      InterPlan Systems

                      Comment


                      • #12
                        I want to say thank you for all of your comments and suggestions. They have all been very helpful.

                        Andrew

                        ------------------

                        Comment


                        • #13
                          Inline assembler works much faster
                          Code:
                          #Compile Exe
                          #Dim All
                          
                          Function PbMain
                             Dim t1 As Single, t2 As Single, i As Long
                             Dim Extract_TWO_Bits As Byte, TheBYTE As Byte, Position As Byte
                             TheBYTE = 121
                             Position = 4
                             
                             t1 = Timer
                             For i = 1 To 10000000
                               
                               If Position = 0 Then Extract_TWO_Bits = (TheBYTE And 3) Else _
                               If Position = 2 Then Extract_TWO_Bits = (TheBYTE And 12) \ 4  Else _
                               If Position = 4 Then Extract_TWO_Bits = (TheBYTE And 48) \ 16 Else _
                                  Extract_TWO_Bits = TheBYTE \ 64
                             Next
                          
                             t2 = Timer
                             MsgBox Format$(1000 * (t2 - t1), "# ms"), , Str$(Extract_TWO_Bits)
                          
                             t1 = Timer
                             For i = 1 To 10000000
                                ! MOV AL, TheByte
                                ! MOV CL, Position
                                ! SHR AL, CL
                                ! AND AL, 3
                                ! MOV Extract_TWO_Bits, AL
                             Next
                          
                             t2 = Timer
                             MsgBox Format$(1000 * (t2 - t1), "# ms"), , Str$(Extract_TWO_Bits)
                          
                             t1 = Timer
                             For i = 1 To 10000000
                                 Extract_TWO_Bits = TheByte
                                 Shift Right Extract_TWO_Bits, Position
                                 Extract_TWO_Bits = Extract_TWO_Bits And &H03
                             Next
                             t2 = Timer
                             MsgBox Format$(1000 * (t2 - t1), "# ms"), , Str$(Extract_TWO_Bits)
                          
                          End Function
                          ------------------
                          E-MAIL: [email protected]

                          Comment


                          • #14
                            How would you write the Assembeler to go Backwards, mimicking the following function:

                            Code:
                            Private Sub Set_TWO_Bits(TheBYTE As Byte, BitsTOSet As Integer, Position As Integer)
                            ' This routine takes a Byte and then sets 2 of its bits to the value
                            'specified in "BitsTOSet".  It sets the bits located in the byte
                            'begining at the position specified by the "Position" parameter
                            
                               Select Case Position
                                
                                 Case 0     '// Sets BITS 0 and 1 to the value of BitsTOSet
                                 TheBYTE = TheBYTE Or BitsTOSet
                                    
                                 Case 2     '// Sets BITS 2 and 3 to the value of BitsTOSet
                                 TheBYTE = TheBYTE Or (BitsTOSet * 4)
                                    
                                 Case 4     '// Sets BITS 4 and 5 to the value of BitsTOSet
                                 TheBYTE = TheBYTE Or (BitsTOSet * 16)
                                    
                                 Case 6     '// Sets BITS 6 and 7 to the value of BitsTOSet
                                 TheBYTE = TheBYTE Or (BitsTOSet * 64)
                                    
                               End Select

                            Originally posted by Semen Matusovski:
                            Inline assembler works much faster
                            Code:
                            #Compile Exe
                            #Dim All
                            
                            Function PbMain
                               Dim t1 As Single, t2 As Single, i As Long
                               Dim Extract_TWO_Bits As Byte, TheBYTE As Byte, Position As Byte
                               TheBYTE = 121
                               Position = 4
                               
                               t1 = Timer
                               For i = 1 To 10000000
                                 
                                 If Position = 0 Then Extract_TWO_Bits = (TheBYTE And 3) Else _
                                 If Position = 2 Then Extract_TWO_Bits = (TheBYTE And 12) \ 4  Else _
                                 If Position = 4 Then Extract_TWO_Bits = (TheBYTE And 48) \ 16 Else _
                                    Extract_TWO_Bits = TheBYTE \ 64
                               Next
                            
                               t2 = Timer
                               MsgBox Format$(1000 * (t2 - t1), "# ms"), , Str$(Extract_TWO_Bits)
                            
                               t1 = Timer
                               For i = 1 To 10000000
                                  ! MOV AL, TheByte
                                  ! MOV CL, Position
                                  ! SHR AL, CL
                                  ! AND AL, 3
                                  ! MOV Extract_TWO_Bits, AL
                               Next
                            
                               t2 = Timer
                               MsgBox Format$(1000 * (t2 - t1), "# ms"), , Str$(Extract_TWO_Bits)
                            
                               t1 = Timer
                               For i = 1 To 10000000
                                   Extract_TWO_Bits = TheByte
                                   Shift Right Extract_TWO_Bits, Position
                                   Extract_TWO_Bits = Extract_TWO_Bits And &H03
                               Next
                               t2 = Timer
                               MsgBox Format$(1000 * (t2 - t1), "# ms"), , Str$(Extract_TWO_Bits)
                            
                            End Function


                            ------------------

                            Comment


                            • #15
                              To Bern and Mike, what if I wanted to go backwards: Like the following Code:

                              Code:
                              Private Sub Set_TWO_Bits(TheBYTE As Byte, BitsTOSet As Integer, Position As Integer)
                              ' This routine takes a Byte and then sets 2 of its bits to the value
                              ' specified in "BitsTOSet".  It sets the bits located in the byte
                              ' beginning at the position specified by the "Position" parameter
                              
                              
                                  Select Case Position
                                  
                                      Case 0     '// Sets BITS 0 and 1 to the value of BitsTOSet
                                          TheBYTE = TheBYTE Or BitsTOSet
                                      
                                      Case 2     '// Sets BITS 2 and 3 to the value of BitsTOSet
                                          TheBYTE = TheBYTE Or (BitsTOSet * 4)
                                      
                                      Case 4     '// Sets BITS 4 and 5 to the value of BitsTOSet
                                          TheBYTE = TheBYTE Or (BitsTOSet * 16)
                                      
                                      Case 6     '// Sets BITS 6 and 7 to the value of BitsTOSet
                                          TheBYTE = TheBYTE Or (BitsTOSet * 64)
                                      
                                  End Select
                              
                              End Sub
                              Is there a function which could be written using the SHIFT command which accomplishes the same objective as the above Sub, but in a more efficient and streamlined manner?

                              Thanks in Advance.

                              Best regards,

                              Andrew Peskin
                              [email protected]

                              ------------------

                              Comment


                              • #16
                                Semen, I like your ASM example. Can you help me translate to LONGS
                                instead of BYTES? I tried converting to EAX but got strange results.
                                I'm not sure what registers are safe to use:

                                Code:
                                'translate following lines to ASM
                                'Temp & Source are LONG
                                '     Temp = Source
                                '     SHIFT RIGHT Temp, 6
                                '     INCR Temp
                                
                                'Following does not work, AL is a BYTE or WORD?
                                      ! MOV AL, Source
                                      ! SHR AL, 6
                                      ! INC AL
                                      ! MOV Temp, AL

                                Andrew,

                                Depending on the situation in your code, you might either use

                                Code:
                                BIT [RE]SET source, bit#
                                or use a mask for the bits instead of shifting. Ie.:

                                Code:
                                InverseMask = &HF3 'Used to clear bits 2&3 (0 base)
                                Mask =  &H04       'Set bit 2
                                temp = source AND InverseMask  'Clear bits of interest
                                temp = source OR Mask          'Set needed bits


                                ------------------
                                Bernard Ertl
                                Bernard Ertl
                                InterPlan Systems

                                Comment


                                • #17
                                  Andrew --

                                  Code:
                                  #Compile Exe
                                  #Dim All
                                  
                                  Function PbMain
                                     Dim t1 As Single, t2 As Single, i As Long
                                     Dim Set_TWO_Bits As Byte, TheBYTE As Byte, BitsTOSet As Byte, Position As Byte
                                  
                                     TheBYTE = 1253
                                     BitsTOSet = 2
                                     Position = 4
                                     
                                     t1 = Timer
                                     For i = 1 To 10000000
                                       If Position = 0 Then Set_TWO_Bits = TheBYTE Or BitsTOSet Else _
                                       If Position = 2 Then Set_TWO_Bits = TheBYTE Or (BitsTOSet * 4)  Else _
                                       If Position = 4 Then Set_TWO_Bits = TheBYTE Or (BitsTOSet * 16) Else _
                                                            Set_TWO_Bits = TheBYTE Or (BitsTOSet * 64)
                                     Next
                                     t2 = Timer
                                     MsgBox Format$(1000 * (t2 - t1), "# ms"), , Str$(Set_TWO_Bits)
                                     t1 = Timer
                                     For i = 1 To 10000000
                                        ! MOV AL, BitsTOSet
                                        ! MOV CL, Position
                                        ! SHL AL, CL
                                        ! MOV AH, TheBYTE
                                        ! OR  AH, AL
                                        ! MOV Set_TWO_Bits, AH
                                     Next
                                     t2 = Timer
                                     MsgBox Format$(1000 * (t2 - t1), "# ms"), , Str$(Set_TWO_Bits)
                                   End Function
                                  ------------------
                                  E-MAIL: [email protected]

                                  Comment


                                  • #18
                                    How would you Set Bits 0 & 1, or Bits 2 & 3, or Bits 4 & 5, or Bits 6 & 7 to a specific value?

                                    Is there something similar to the other example you posted for extracting Bits?

                                    Thanks.

                                    Andrew


                                    Originally posted by Bern Ertl:
                                    Semen, I like your ASM example. Can you help me translate to LONGS
                                    instead of BYTES? I tried converting to EAX but got strange results.
                                    I'm not sure what registers are safe to use:

                                    Code:
                                    'translate following lines to ASM
                                    'Temp & Source are LONG
                                    '     Temp = Source
                                    '     SHIFT RIGHT Temp, 6
                                    '     INCR Temp
                                    
                                    'Following does not work, AL is a BYTE or WORD?
                                          ! MOV AL, Source
                                          ! SHR AL, 6
                                          ! INC AL
                                          ! MOV Temp, AL

                                    Andrew,

                                    Depending on the situation in your code, you might either use

                                    Code:
                                    BIT [RE]SET source, bit#
                                    or use a mask for the bits instead of shifting. Ie.:

                                    Code:
                                    InverseMask = &HF3 'Used to clear bits 2&3 (0 base)
                                    Mask =  &H04       'Set bit 2
                                    temp = source AND InverseMask  'Clear bits of interest
                                    temp = source OR Mask          'Set needed bits



                                    ------------------

                                    Comment


                                    • #19
                                      Probably, there is better variant, but this works also not bad.
                                      Code:
                                      #Compile Exe
                                      #Dim All
                                      
                                      Function PbMain
                                         Dim t1 As Single, t2 As Single, i As Long
                                         Dim Set_TWO_Bits As Byte, TheBYTE As Byte, Position As Byte, NewValue As Byte
                                      
                                         TheBYTE =  &B10110101
                                         NewValue = &B10
                                         Position = 4
                                       
                                         t1 = Timer
                                         For i = 1 To 10000000
                                            ! MOV AL, &B11
                                            ! MOV CL, Position
                                            ! SHL AL, CL
                                            
                                            ! MOV AH, TheByte
                                            ! MOV DL, AH
                                            ! AND AH, AL
                                            ! SUB DL, AH
                                            
                                            ! MOV AL, NewValue
                                            ! SHL AL, CL
                                            ! ADD DL, AL
                                            ! MOV Set_TWO_Bits, DL
                                         Next
                                         t2 = Timer
                                         MsgBox Format$(1000 * (t2 - t1), "# ms"), , Bin$(Set_TWO_Bits, 8)
                                       End Function
                                      ------------------
                                      E-MAIL: [email protected]

                                      Comment


                                      • #20
                                        Bern -
                                        If you work with Long
                                        ! MOV EAX, Source
                                        ! SHR EAX, 6
                                        ! INC EAX
                                        ! MOV Temp, EAX




                                        ------------------
                                        E-MAIL: [email protected]

                                        Comment

                                        Working...
                                        X