Announcement

Collapse
No announcement yet.

Timer speed

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

  • Timer speed

    In the Life program, Timer is called hundreds of times a second. It's always been my understanding calls to Timer are "expensive" (CPU time eaters) so I thought maybe I could get around at least some of the cost by using
    Code:
    '
    Function Faux_Timer As Dword
      'Less calls to Timer?
     
      Incr Faux_Timer_Ctr
      If Faux_Timer_Ctr > 100 Then
         Reset Faux_Timer_Ctr
         Last_Timer_Set = Timer
      End If
      Function = Last_Timer_Set
     
    End Function
    '
    and substituting "Faux_Timer" for "Timer" in the code but there isn't any appreciable times savings, slower even if anything.

    Just another blind alley going up in smoke, I guess. {sigh}

    ============================================
    People will not remember
    what you did or what you said.
    People will remember how you made them feel.
    LadyHawke
    ============================================
    Last edited by Gösta H. Lovgren-2; 9 Nov 2008, 12:06 AM.
    It's a pretty day. I hope you enjoy it.

    Gösta

    JWAM: (Quit Smoking): http://www.SwedesDock.com/smoking
    LDN - A Miracle Drug: http://www.SwedesDock.com/LDN/

  • #2
    Code:
    '
    Function Faux_Timer As Dword
      'Less calls to Timer?
     
      Incr Faux_Timer_Ctr
      If Faux_Timer_Ctr [COLOR="Blue"][b]= 101[/b][/COLOR] Then
         Reset Faux_Timer_Ctr
         Last_Timer_Set = Timer
      End If
      Function = Last_Timer_Set
     
    End Function
    '
    I believe greater than is more expensive then equals. Does change above help the speed?

    Cheers,
    Dale

    Comment


    • #3
      I haven't tried it but....

      As I understand it, For/Next loops are slightly faster using STEP -X. IOW:

      for x = 100 to 1 step -1

      is slightly faster than

      for x = 1 to 100

      So changing your code to:

      Faux_Timer_Ctr = 101 ' Somewhere in your program

      Decr Faux_Timer_Ctr
      If Faux_Timer_Ctr = 0 Then
      ...
      ...

      MIGHT speed things up a bit. Then again, it might not.
      There are no atheists in a fox hole or the morning of a math test.
      If my flag offends you, I'll help you pack.

      Comment


      • #4
        It's always been my understanding calls to Timer are "expensive" (CPU time eaters)
        Why would you think that? Have you tested it?
        While TIMER isn't the faster of functions out there it still takes only 1.6micro seconds to run on my slow PC.
        Code:
        'PBCC5.0 program
        FUNCTION PBMAIN() AS LONG
        LOCAL k,b AS EXT
        limit&=1000000
        k=TIMER
        FOR r& = 1 TO limit&
        b=TIMER
        NEXT
        k=(TIMER-k)/limit& * 1000000
        PRINT "Time per TIMER call=";k; "micro seconds"
        WAITKEY$
        END FUNCTION

        Comment


        • #5
          Dale,
          there's no reason from the CPU's point of view that the speed of the comparison should be different.
          If the compiler does its job then the 2 comparisons will take the exact same time and use the same code except for the choice of which one conditional branch instruction to use at the end. The CPU has lots of conditional branch instructions to choose from, they all run at the same speed.

          You CAN speed up that code by using LONGs instead of DWORDs.



          Mel,
          I think you misunderstand.
          There's no need for a FOR/NEXT loop to be a different speed counting up or down.
          In cases where the loop counter is not referenced within the loop then the compiler will optimise the counter to count down to zero which saves on one compare instruction as the zero flag will be set already by the update of the loop counter and the loop can exit on that condition.
          This isn't done if you specify a terminal loop count of zero, only if the compiler sees the shortcut for itself.

          Paul.

          Comment


          • #6
            Gösta, I haven't been looking at Gary's code or yours as I've been busy on other things but I was drawn to this thread by virtue of its title.

            Since I haven't been looking what I am about to say may be irrelevant so, obviously, ignore if so.

            Since, from PB documentation, the resolution of Timer is about 1/100 of a second on NT-based platforms, or 1/18th of a second on earlier platforms, "Timer is called hundreds of times a second" will yield the same value within the resolution.

            Anyway, that may be irrelevant.

            With regard to the time spent calling Timer another way of getting elapsed time is to use QueryPerformanceCounter.

            The following compares the two approaches. I'm using x as Double but note that tmr and so on in Life uses Longs.

            Using QueryPerformanceCounter is about 6 times faster.
            Code:
            #COMPILE  EXE
            #Register None
            #Dim      All
            #TOOLS    OFF
             
            %NOMMIDS = 1
            %NOGDI = 1
             
            #Include "WIN32API.INC"
             
            '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            Global qFreq, qOverhead, qStart, qStop As Quad
            Global f As String
             
            Macro InitializeTimer
              f = "#####.####"
              QueryPerformanceFrequency qFreq
              QueryPerformanceCounter qStart ' Intel suggestion. First use may be suspect
              QueryPerformanceCounter qStart ' So, wack it twice <smile>
              QueryPerformanceCounter qStop
              qOverhead = qStop - qStart     ' Relatively small
            End Macro
             
            Macro StartTimer = QueryPerformanceCounter qStart
            Macro StopTimer = QueryPerformanceCounter qStop
             
            Macro sTimeTaken = Using$(f,(qStop - qStart - qOverhead)*1000/qFreq) + "ms"
            Macro nTimeTaken = (qStop - qStart - qOverhead)*1000/qFreq
            '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
             
            Function PBMain() As Long
            Local i As Long, x As Double, qCount As Quad
             
              InitializeTimer
             
              StartTimer
              For i = 1 To 1000000
                x = Timer                      ' in seconds
              Next
              StopTimer
              MsgBox sTimeTaken
             
              StartTimer
              For i = 1 To 1000000
                QueryPerformanceCounter qCount
                x = qCount/qFreq               ' in seconds
              Next
              StopTimer
              MsgBox sTimeTaken
             
            End Function

            Comment


            • #7
              There are many ways to do timings.
              This one will run in the background using almost no CPU time but the timer will increment every millisecond and is accessed as fast as reading a global variable, i.e. very fast.
              Code:
              $INCLUDE "WIN32API.INC"
              
              GLOBAL MyGlobalTimer AS LONG
              
              FUNCTION TimerUpdate ( BYVAL uID AS LONG, BYVAL uMsg AS LONG, _
                                      BYVAL dwUser AS LONG, BYVAL dw1 AS LONG, BYVAL dw2 AS LONG) AS LONG
              'this is the routine that is run everytime the timer triggers
              'we just increment our global timer variable
              
                    INCR MyGlobalTimer
              END FUNCTION
              
              
              FUNCTION WINMAIN (BYVAL hInstance     AS LONG, _
                                BYVAL hPrevInstance AS LONG, _
                                BYVAL lpCmdLine           AS ASCIIZ PTR, _
                                BYVAL iCmdShow      AS LONG) AS LONG
              
              'start the timer
              '1=milliseconds between triggers, 0=maximum timer resolution, TimerUpdate=the routine to call
              TimerHandle& = timeSetEvent ( BYVAL 1, BYVAL 0, CODEPTR(TimerUpdate), BYVAL 0&, BYVAL %TIME_PERIODIC)
              
              PRINT "press a key to end."
              DO
                 LOCATE 10,10
                 PRINT "Time=";FORMAT$(MyGlobalTimer/1000,"#######.###");"secs."
                 SLEEP 1
                 LOOP UNTIL INSTAT
              
              'stop the timer before exit
              timeKillEvent TimerHandle&
              
              END FUNCTION

              Comment


              • #8
                Originally posted by Paul Dixon View Post
                Why would you think that?
                Don't really know. Must have been something I picked up here. Lord knows I don't talk programming with the wife.
                Have you tested it?
                I have now.
                While TIMER isn't the faster of functions out there it still takes only 1.6micro seconds to run on my slow PC.
                Your "slow" machine is way faster than mine. Takes 2.6ms here
                '
                Code:
                PBWin 9.00 - WinApi 05/2008 - XP Pro SP3
                #Compile Exe                                
                #Dim All 
                #Include "WIN32API.INC"
                #Include "COMDLG32.INC"
                Function PBMain
                   Local k,b As Ext
                   Local limit, r As Long
                   limit&=1000000
                   k=Timer
                   For r& = 1 To limit&
                      b=Timer
                   Next
                   k=(Timer-k)/limit& * 1000000
                 
                   ? Using$("Time per TIMER call= #.# 'micro seconds'", k)
                End Function
                '
                Last edited by Gösta H. Lovgren-2; 9 Nov 2008, 08:05 AM.
                It's a pretty day. I hope you enjoy it.

                Gösta

                JWAM: (Quit Smoking): http://www.SwedesDock.com/smoking
                LDN - A Miracle Drug: http://www.SwedesDock.com/LDN/

                Comment


                • #9
                  Gösta,
                  do you really mean 2.6ms (0.0026 seconds) or do you mean 2.6us (0.0000026 seconds).
                  If it's the first then I think your PC needs winding up!
                  The second one is more likely and 2.6us called a few hundred times a second is still well under 0.1% of the CPU time so it should be acceptable.

                  Paul.

                  Comment


                  • #10
                    Dave,
                    The results of your test are:

                    2667.1596ms
                    340.6663ms

                    How that compares to Paul's 1.6ms & my 2.6ms is for you to tell us/me.

                    Code used:'
                    Code:
                     #Compile  Exe
                    #Register None
                    #Dim      All
                    #Tools    Off
                    %NOMMIDS = 1
                    %NOGDI = 1
                    #Include "WIN32API.INC"
                    '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                    Global qFreq, qOverhead, qStart, qStop As Quad
                    Global f As String
                    Macro InitializeTimer
                      f = "#####.####"
                      QueryPerformanceFrequency qFreq
                      QueryPerformanceCounter qStart ' Intel suggestion. First use may be suspect
                      QueryPerformanceCounter qStart ' So, wack it twice <smile>
                      QueryPerformanceCounter qStop
                      qOverhead = qStop - qStart     ' Relatively small
                    End Macro
                    Macro StartTimer = QueryPerformanceCounter qStart
                    Macro StopTimer = QueryPerformanceCounter qStop
                    Macro sTimeTaken = Using$(f,(qStop - qStart - qOverhead)*1000/qFreq) + "ms"
                    Macro nTimeTaken = (qStop - qStart - qOverhead)*1000/qFreq
                    '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                    Function PBMain() As Long
                    Local i As Long, x As Double, qCount As Quad, s$
                      InitializeTimer
                      StartTimer
                      For i = 1 To 1000000
                        x = Timer                      ' in seconds
                       Next
                      StopTimer
                      s$ =  sTimeTaken & $CrLf 
                      
                      StartTimer
                      For i = 1 To 1000000
                        QueryPerformanceCounter qCount
                        x = qCount/qFreq               ' in seconds
                      Next
                      StopTimer
                      MsgBox sTimeTaken        
                      s$ = s$ & sTimeTaken
                      ClipBoard Set Text s$ To i
                    End Function'
                    It's a pretty day. I hope you enjoy it.

                    Gösta

                    JWAM: (Quit Smoking): http://www.SwedesDock.com/smoking
                    LDN - A Miracle Drug: http://www.SwedesDock.com/LDN/

                    Comment


                    • #11
                      Gösta,
                      How that compares to Paul's 1.6ms & my 2.6ms is for you to tell us/me.
                      Mine is not 1.6ms it's 1.6us, that's a thousand times faster.

                      Paul.

                      Comment


                      • #12
                        Originally posted by Paul Dixon View Post
                        Gösta,
                        do you really mean 2.6ms (0.0026 seconds) or do you mean 2.6us (0.0000026 seconds).
                        If it's the first then I think your PC needs winding up!
                        The second one is more likely and 2.6us called a few hundred times a second is still well under 0.1% of the CPU time so it should be acceptable.

                        Paul.
                        Paul, I used the code you first posted (and I adapted to run in PBWin - posted above) so the time naming convention would be the same as yours. It may well be my machine (even more likely its owner) needs tuning. I been tuned up more than once in my life actually, but those are stories for another time another place ... {grin}
                        It's a pretty day. I hope you enjoy it.

                        Gösta

                        JWAM: (Quit Smoking): http://www.SwedesDock.com/smoking
                        LDN - A Miracle Drug: http://www.SwedesDock.com/LDN/

                        Comment


                        • #13
                          Gösta,
                          I get
                          Code:
                           1609.6884ms
                           1349.4648ms
                          with Dave's code. You need to divide those figures by 1,000,000 to get the time for a single call so that gives 1.6us for TIMER (just as it did earlier) and 1.3us with QueryPerformaneCounter.

                          I can now see that your PC would give 2.6us with TIMER and is no longer in need of winding up!

                          Paul.

                          Comment


                          • #14
                            Originally posted by Paul Dixon View Post
                            Gösta,
                            I get
                            Code:
                             1609.6884ms
                             1349.4648ms
                            with Dave's code. You need to divide those figures by 1,000,000 to get the time for a single call so that gives 1.6us for TIMER (just as it did earlier) and 1.3us with QueryPerformaneCounter.

                            I can now see that your PC would give 2.6us with TIMER and is no longer in need of winding up!

                            Paul.
                            Code:
                            'My results with Dave's Code
                            2667.1596ms
                            340.6663ms
                             
                            'Paul's results
                            1609.6884ms
                             1349.4648ms
                            Clearly Paul is far faster(almost twice as fast) as my machine. So it could use a little "winding" I guess. I have a 1.86ghz Dell XPS 710 w/dual core and I'd guess Paul has 3ghz and it's throughputting almost 4 times faster (1349 to 340).

                            ==================================
                            "If you are going through hell,
                            keep going."
                            Sir Winston Churchill (1874-1965)
                            ==================================
                            It's a pretty day. I hope you enjoy it.

                            Gösta

                            JWAM: (Quit Smoking): http://www.SwedesDock.com/smoking
                            LDN - A Miracle Drug: http://www.SwedesDock.com/LDN/

                            Comment


                            • #15
                              Gösta,
                              mine is a 1.9GHz Athlon.
                              The important result is that it only takes a few microseconds to read the TIMER. You're reading it hundreds of times a second so the total time spent reading the timer is under 0.001s for every 1 second that the program runs. If you're after significant savings in time then you need to look elsewhere because reading the TIMER is not taking up very much time at all.

                              Paul.

                              Comment


                              • #16
                                I'll be honest up front, I have NOT looked at the code in question.

                                But from that vacuum I have to ask: What kind of application NEEDS to read the timer so often one would even care about the best way to do so? Or so often that performance is impacted?

                                Seems to me instead of reading the timer a program should be DOING whatever it is it's supposed to do instead of worrying about what time it is.

                                Reminds me of employees whose top job priority is checking to see if it's lunchtime yet.
                                Michael Mattias
                                Tal Systems (retired)
                                Port Washington WI USA
                                [email protected]
                                http://www.talsystems.com

                                Comment


                                • #17
                                  I looked at the Life code and had this thought: if you update the title information less frequently, you will see a speed improvement. So if you don't mind updating the title every say 10 generations, you might get ~14% speed improvement like I did.
                                  Code:
                                  'enclose Stasis & Set_Header macros thusly:
                                   LOCAL ctr3 aAS LONG
                                     INCR ctr3
                                     IF ctr3 = 10 THEN
                                        Stasis
                                        Set_Header
                                        ctr3 = 0
                                     END IF
                                  'and down in the Set_Header macro make:
                                     Generations = Generations + 10 '10 here is to be equal to ctr3 IF value
                                  Last edited by John Gleason; 9 Nov 2008, 12:44 PM. Reason: tweaked ctr3 IF limit (again)

                                  Comment


                                  • #18
                                    Originally posted by John Gleason View Post
                                    I looked at the Life code and had this thought: if you update the title information less frequently, you will see a speed improvement. So if you don't mind updating the title every say 10 generations, you might get ~14% speed improvement like I did.
                                    Good thought John. I'll certainly look into that. Dunno why I didn't think of it myself. Certainly not trying to measure anything in fractions of a second.

                                    From a deeply distant black void of a vacuum came:
                                    I'll be honest up front, I have NOT looked at the code in question.

                                    But from that vacuum I have to ask: What kind of application NEEDS to read the timer so often one would even care about the best way to do so? Or so often that performance is impacted?
                                    How about an application you haven't looked at, yet are questioning? And really, does the application have anything to do with whether or not there is a faster way to measure time?

                                    Seems to me instead of reading the timer a program should be DOING whatever it is it's supposed to do instead of worrying about what time it is.
                                    Perhaps maybe just possibly it could be what the program SHOULD be doing is checking the Timer. But, of course you couldn't know that because you haven't looked at it.

                                    Paul said:
                                    Gösta,
                                    mine is a 1.9GHz Athlon.
                                    Wow, sorta makes a case for and "old" Athlon over a (relatively) new Intel, doesn't it (all other things being equal).

                                    The important result is that it only takes a few microseconds to read the TIMER. You're reading it hundreds of times a second so the total time spent reading the timer is under 0.001s for every 1 second that the program runs. If you're after significant savings in time then you need to look elsewhere because reading the TIMER is not taking up very much time at all.

                                    Paul.
                                    You are probably undoubtedly unquestionably right, but several things are happening here. I'm picking up a lot of education on Timer which will no doubt be useful for unimaginable event in the unforseeeable future.

                                    Another is I'll try to implement your timing method just to see how much difference it might actually make. If it does improve performance significantly, cool. If it doesn't, then we'll know. One thing neat about this program is it's so repetitively CPU intensive over long periods, it's relatively easy to test different methods (see Pointers thread).

                                    Another is, I think other PB'ers are benefitting as well, just by lurking, especially the less, aaahhh, experienced like myself.

                                    And the final thing is ... I'm just having fun. If I wasn't playing here I'd just be sitting around watching tv or {eew} reading books or some other equally even more useless endeavor.

                                    =======================================
                                    "Looking foolish does the spirit good."
                                    John Updike
                                    =======================================

                                    (Makes me laugh too)
                                    It's a pretty day. I hope you enjoy it.

                                    Gösta

                                    JWAM: (Quit Smoking): http://www.SwedesDock.com/smoking
                                    LDN - A Miracle Drug: http://www.SwedesDock.com/LDN/

                                    Comment


                                    • #19
                                      And the final thing is ... I'm just having fun. If I wasn't playing here I'd just be sitting around watching tv or {eew} reading books or some other equally even more useless endeavor.
                                      Like checking to see if it's lunchtime????
                                      Just having fun.
                                      Rod
                                      In some future era, dark matter and dark energy will only be found in Astronomy's Dark Ages.

                                      Comment


                                      • #20
                                        Originally posted by John Gleason View Post
                                        I looked at the Life code and had this thought: if you update the title information less frequently, you will see a speed improvement. So if you don't mind updating the title every say 10 generations, you might get ~14% speed improvement like I did.
                                        John,
                                        Here's the counter I installed:
                                        Code:
                                        '  Incr Header_Set_Ctr 'John Geason suggestion, save time doing header instead of multiple times per second
                                        '    If Header_Set_Ctr > 10 Then 'times before 24, 32, 41 updates per sec for 1,000 generations
                                               Header_Set               'times w ctr  36, 47, 28 using counter
                                        '       Reset Header_Set_Ctr                
                                        '    End If
                                        Update Tests with Without counter (remmed out as above) - 640X480 screen
                                        Appropriate Pointers = 55
                                        No pointers = 41
                                        All Pointers = 34
                                        Update Tests with With counter (un remmed)
                                        Appropriate Pointers = 61 10%
                                        No pointers = 47 13%
                                        All Pointers = 35 3%
                                        Result are Generations per second for 1,000 generations each. Tests were run 3 times (a lot more actually) JIC there were code or CPU anomalies. The 3 Update methods were tested just because I could. Curious the differences in speed increases between the update methods. Might see a variance of 1 or 2 between runs but seemed to stay reasonably consistent.

                                        ======================================================
                                        "Oil prices have fallen lately.
                                        We include this news for the benefit of gas stations,
                                        which otherwise wouldn't learn of it for six months."
                                        William D. Tammeus
                                        ======================================================
                                        It's a pretty day. I hope you enjoy it.

                                        Gösta

                                        JWAM: (Quit Smoking): http://www.SwedesDock.com/smoking
                                        LDN - A Miracle Drug: http://www.SwedesDock.com/LDN/

                                        Comment

                                        Working...
                                        X