Announcement

Collapse
No announcement yet.

Speed of Creating and destroying LOCAL vars vs, GLOBAL Vars

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

  • Speed of Creating and destroying LOCAL vars vs, GLOBAL Vars

    If I have a function that is called alot, and that function has 20 LOCAL vars in it, how much time would I save by making all the vars GLOBAL so that they are not continually created and destroyed?

    Speed is important in this dll because it is applied across 80 charts and small fractions start to really add up.



    ------------------
    Kind Regards
    Mike

  • #2
    Probably not that much, but try making them STATIC to the sub/function and see what difference it makes. Note that if you still have to initialize a lot of the variables, you'll probably lose some of the advantage you gained by moving away from LOCAL.

    The best test is to try it for yourself...

    Have you optimized the sub/function code itself as much as possible? That is, using Register Variables, using long integers everywhere possible, etc.

    ------------------
    Lance
    PowerBASIC Support
    mailto:[email protected][email protected]</A>
    Lance
    mailto:[email protected]

    Comment


    • #3
      LOCAL scalar variables aren't really "created," are they?

      It would seem to me the allocated space for them is the stack, and the corresponding address is assigned at compile time as an offest from the current stack pointer.

      Dynamic strings and arrays might be different???

      MCM


      Michael Mattias
      Tal Systems (retired)
      Port Washington WI USA
      [email protected]
      http://www.talsystems.com

      Comment


      • #4
        Dynamic strings and dynamic arrays need to be allocated via Windows calls, which can be slow.
        The overhead of allocating local scalars on the stack is minimal, although they do have to be
        initialized. It would be unusual for this overhead to be significant, however.

        Chances are, it will be more useful to look elsewhere for optimization.

        ------------------
        Tom Hanlin
        PowerBASIC Staff

        Comment


        • #5
          Ooooh REGISTER variables, what are they? Hmmm let me see.......
          Cool!
          Great idea Lance! (again!!) No wonder you get the big bucks

          So I have two unavoidable loops. They are quite simple but they have alot of work to do in the Function that is at the guts of this Dll.

          FUNCTION Back(BYVAL Past AS LONG) AS LONG ' Find Push Stack Element
          IF Past <= Ix THEN
          FUNCTION = Ix - Past
          ELSE
          FUNCTION = Ix - Past + 1 + NumElem
          END IF
          END FUNCTION
          .....

          GLOBAL Stk() AS SeriesVariableType

          LOCAL Sum1 AS SINGLE, Sum2 AS SINGLE
          LOCAL Aux AS SINGLE
          LOCAL j AS INTEGER
          LOCAL Old AS LONG


          FOR j = 1 TO BarsBack
          Old = Back(j)
          Sum1 = Sum1 + Stk(0,Old).Price
          Sum2 = Sum2 + Stk(0,Old).Price * (Aux - j)
          NEXT

          This is where I guess I would get the most speed increase.
          SO j is an obvious candidate for a REGISTER variable
          and I guess Old woudld be the other integer. Floats Sum1, Sum2, and Aux?

          But would it be faster to pull the guts out of the Function Back into the loop and assign some of those variables to REGISTERs?

          ------------------
          Kind Regards
          Mike

          Comment


          • #6
            Dissolving function Back() and inlining its code would be faster.
            Any code executed in functions you frequently call run faster if
            inlined so the function was not called. If speed is a priority
            I would favor more inline code for functions which get called a
            lot but from only a small number of locations in a program. It's
            just a question of how fast you want it to be. Perhaps PowerBASIC
            will someday have a compiler directive to create inline code for specified functions
            anytime a call is made to that function. Until then, just copy and paste for speed (with moderation).

            Ron

            Comment


            • #7
              1. Like Lance says, skip Integer and use LONG in 32-bit Windows.
              2. Move the function code, Back(), into the loop. Function calls
              always takes extra time, so if code isn't too big, it's better
              to make it "inline" instead.

              Register variables? Never managed to get a consistent result from
              using that thing myself. Don't know if it's me or my computers, but
              everytime I try to optimize via Register variables, I get different
              results depending on what computer I test the code in. Sometimes a
              bit faster, sometimes not. If I don't care and let the compiler take
              care of it, results become far more consistent. People keep saying
              it's a great optimizing tool, so I probably do something wrong. No
              big deal - PB produces enough tight and fast code as it is, so..


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

              Comment


              • #8
                Perhaps PowerBASIC will someday have a compiler directive to create inline code for specified functions anytime a call is made to that function.
                The IBM mainframe COBOL compiler already does this, and goes one better: if it can determine the number of loops in ANY iterative structure, it unrolls and inlines the code. In BASIC, this would look like...

                Code:
                FOR I = 1 to 3
                 J = J + I^2
                NEXT I
                This would become..
                Code:
                J = J + 1^2 + 2^2 + 3^2
                That optimizer will also re-arrange arithmetic operations using the commutative and associative rules of math (bet you ain't used them since high school!) to make the generated code more efficient.

                Of course, for 75K USD, you'd expect some optimization from a compiler..


                MCM

                Michael Mattias
                Tal Systems (retired)
                Port Washington WI USA
                [email protected]
                http://www.talsystems.com

                Comment


                • #9
                  Can't agree that integer works slowly than long.
                  At least, it's not so on my PC (PIII-800, Win2000).
                  Depends from OS ? Very doubt. From processor ? Yes, sure.

                  Code:
                     #Compile Exe
                     #Dim All
                     #Register None
                     #Include "Win32Api.INC"
                  
                     Function PbMain
                        Dim a(1000) As Long, i  As Long, j As Long, t1 As Single, t2 As Single
                        t1 = Timer
                        For i = 1 To 100000
                           For j = 1 To 1000
                              a(j) = j / 2
                           Next
                        Next
                        t2 = Timer
                        MsgBox Str$(t2 - t1)
                  
                        Dim aa(1000) As Integer, ii  As Integer, jj As Integer, tt1 As Single, tt2 As Single
                        tt1 = Timer
                        For ii = 1 To 100000
                           For jj = 1 To 1000
                              aa(jj) = jj / 2
                           Next
                        Next
                        tt2 = Timer
                        MsgBox Str$(tt2 - tt1)
                        
                     End Function
                  Have somebody correct test to compare integer vs long ?
                  (one operation, of course, doesn't prove something)

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

                  Comment


                  • #10
                    I declared the Integers as REGISTER LONGs ok, but when I delcare my SINGLEs as REGISTER EXE my program crashes with " illegal operation.. ".

                    I assumethats because the EXE is a DOUBLE and not a single. In which case do I have to convert it with CDBL() everytime in the loop?

                    I cant declare the array as a REGISTER variable and everything in it is SINGLE. So wouldnt the CDBL() conversion slow everything up again?

                    ------------------
                    Kind Regards
                    Mike

                    Comment


                    • #11
                      I have brought the code from Function Back "inline".

                      After much experimenting I found I could get rid of the IF statement which I though was a time consuming operation. However I have to do 2 MODs in its place.

                      GLOBAL Ix AS LONG ' the Array Index
                      GLOBAL NumElem AS LONG ' Number of Array Elements
                      REGISTER j AS LONG, Old AS LONG

                      IF j > Ix Then Old = Ix - j + 1 + NumElem else Old = Ix - j' Find position in the Push Stack
                      Old = (Ix - j + 1 + NumElem) MOD NumElem) MOD (1 + NumElem)' Find position in the Push Stack

                      Which is faster?

                      ------------------
                      Kind Regards
                      Mike

                      Comment


                      • #12
                        I think IF/THEN should be a bit faster - especially if used in right
                        order. By that I mean, put most likely case first. Are you sure j > Ix
                        more often than the opposite? Sometimes surprising speed difference, if
                        it turns out that 80-90% of the cases are the second, ELSE..

                        Yes Semen, you are right. Have never been able to see any difference
                        between LONG and INTEGER myself, but think some processors can benefit
                        from using LONG's. Feels safer to use LONG in 32-bit environment..


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

                        Comment


                        • #13
                          Since you are not using a REGISTER statement to explicitly define your Register variable(s), you probably want to add a #REGISTER NONE to the very top of that specific function or the compiler will automatically cast the 1st two LONG variables to register variables and ignore the cast for the remaining ones (see #REGISTER DEFAULT for more information).


                          ------------------
                          Lance
                          PowerBASIC Support
                          mailto:[email protected][email protected]</A>
                          Lance
                          mailto:[email protected]

                          Comment


                          • #14
                            Long integer variables, used in a long integer expression are always, in all cases, 100.00% of the time, substantively faster than using integer variables in any class of expression. The above sample code is inaccurate because you are timing a floating point operation, not integer. The "/" operator is floating point only, requiring that the operation be performed in the numeric coprocessor. I'm afraid it tests nothing. PowerBASIC assigns register variables only if you have not done so yourself, explicitly, in your code.

                            Best of luck with this stuff...

                            Bob Zale
                            PowerBASIC Inc.


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

                            Comment


                            • #15
                              Gentlemen,
                              I have to respectfully disagree.
                              I do not see reason why instructions using LONG can be executed faster than instructions using INTEGER.
                              The float point division in the code introduced by Semen just hides how much fast operations with INTEGER are if compared with operations with LONG.
                              I do not have the Pentium processor instructions execution times but based on AMD's Manuals (ATLHON) and on old 486 Manual I can tell that :
                              Addition and subtraction:
                              When possible use INTEGER because it occupies less memory and executes at the same time that LONG.
                              Multiplication and Division
                              When possible use INTEGER because it occupies less memory and executes faster than LONG.

                              Testing PB compiled code on k6-2 550Mhz shows that even addition and subtraction are executed faster with INTEGER !

                              (KISS - Keep It Simple and Small)

                              RValois

                              ------------------
                              http://www.rvalois.com.br/downloads/free/

                              Comment


                              • #16
                                Sorry to have to say so, Mr. Valois, but you are 100.0000% incorrect.

                                In a 32-bit operating system, Long Integer Operations are substantially faster than 16-bit integer operations. Absolutely, unequivocally faster.

                                You are free to do what you wish, but I hope nobody here will take your advice because it will cause programs to execute at a slower speed. It's just that simple.

                                32-bit Integers are the variable of choice.

                                Regards,

                                Bob Zale
                                PowerBASIC Inc.


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

                                Comment


                                • #17
                                  Lets code.
                                  Could someone please execute the code below and report the results ?

                                  [code]
                                  ' modified Semen code
                                  #Compile Exe
                                  #Dim All
                                  #Include "Win32Api.INC"
                                  Function PbMain

                                  Dim aa(10000) As Integer, ii As Integer, jj As Integer, tt1 As Single, tt2 As Single
                                  tt1 = Timer
                                  For ii = 1 To 30000
                                  For jj = 1 To 10000
                                  aa(jj) = jj \ 3
                                  Next
                                  Next
                                  tt2 = Timer
                                  MsgBox " Integer " & Str$(tt2 - tt1)

                                  Dim a(10000) As Long, i As Long, j As Long, t1 As Single, t2 As Single
                                  t1 = Timer
                                  For i = 1 To 30000
                                  For j = 1 To 10000
                                  a(j) = j \ 3
                                  Next
                                  Next
                                  t2 = Timer
                                  MsgBox " Long " & Str$(t2 - t1)


                                  End Function
                                  [ /code]

                                  Mine
                                  Int - 16.96875
                                  long - 20.32031
                                  Win Me k6-2 550Mhz

                                  RValois

                                  ------------------
                                  http://www.rvalois.com.br/downloads/free/

                                  Comment


                                  • #18
                                    Sorry, I forgot the register none.
                                    The correct code:

                                    ' modified Semen code
                                    #Compile Exe
                                    #Register None
                                    #Dim All
                                    #Include "Win32Api.INC"
                                    Function PbMain

                                    Dim aa(10000) As Integer, ii As Integer, jj As Integer, tt1 As Single, tt2 As Single
                                    tt1 = Timer
                                    For ii = 1 To 30000
                                    For jj = 1 To 10000
                                    aa(jj) = jj \ 3
                                    Next
                                    Next
                                    tt2 = Timer
                                    MsgBox " Integer " & Str$(tt2 - tt1)

                                    Dim a(10000) As Long, i As Long, j As Long, t1 As Single, t2 As Single
                                    t1 = Timer
                                    For i = 1 To 30000
                                    For j = 1 To 10000
                                    a(j) = j \ 3
                                    Next
                                    Next
                                    t2 = Timer
                                    MsgBox " Long " & Str$(t2 - t1)


                                    End Function
                                    mine
                                    Integer 16.25781
                                    Long 22.35156


                                    ------------------
                                    http://www.rvalois.com.br/downloads/free/

                                    Comment


                                    • #19
                                      Yes ... let's code
                                      Code:
                                      #Compile Exe
                                      #Register None
                                      #Dim All
                                      #Include "Win32Api.INC"
                                      Function PbMain 
                                      
                                         Dim aa(10000) As Integer, ii As Integer, jj As Integer, tt1 As Single, tt2 As Single
                                         Dim a(10000) As Long, i As Long, j As Long, t1 As Single, t2 As Single
                                         Dim longStop as Long
                                         Dim longStop2 as Long
                                         Dim longStart as Long
                                         Dim iStop as Integer
                                         Dim iStop2 as Integer
                                         Dim iStart as integer
                                      
                                         longStop = 30000
                                         longStop2 = 10000
                                         longStart = 1
                                         iStop = 30000
                                         iStop2 = 10000
                                         iStart = 1
                                         
                                         '- Do the integers
                                         tt1 = Timer
                                         For ii = iStart to iStop
                                            For jj = iStart to iStop2
                                               aa(jj) = jj \ 3
                                            Next
                                         Next
                                         tt2 = Timer
                                         MsgBox " Integer " & Str$(tt2 - tt1) 
                                      
                                         '- Do the longs
                                         t1 = Timer
                                         For i = longStart to longStop
                                            For j = longStart to longStop2
                                               a(j) = j \ 3
                                            Next
                                         Next
                                         t2 = Timer
                                         MsgBox " Long " & Str$(t2 - t1) 
                                      
                                      End Function
                                      On my lowly machine the integer portion takes 39 seconds and the long part takes 33 seconds.
                                      The code above *ensures* that all variables involved are longs when longs are being test and integers when integers are being tested.
                                      When I tested your original code, my results were similar to yours. Now the long code is clearly faster on my machine.
                                      When in doubt ... Bob's probably correct

                                      --Don

                                      ------------------
                                      www.basicguru.com/dickinson
                                      Don Dickinson
                                      www.greatwebdivide.com

                                      Comment


                                      • #20
                                        Thanks Don.

                                        On My machine your code reports:
                                        Integer 16.8
                                        Long 21.6

                                        Mr. Zale is probably correct in some sense. But certainly I'm not
                                        100.0000% wrong.

                                        RValois.

                                        ------------------
                                        http://www.rvalois.com.br/downloads/free/

                                        Comment

                                        Working...
                                        X