Announcement

Collapse
No announcement yet.

Timer speed

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

  • Gösta H. Lovgren-2
    replied
    Thanks the tip, Dave. Never been "Profiled" before. (Well I have but that's another story for another time.) Nifty tool. Really couldn't be easier.

    ==================================
    "Even when all the experts agree,
    they may well be mistaken."

    Bertrand Russell
    ==================================
    Last edited by Gösta H. Lovgren-2; 10 Nov 2008, 08:49 PM.

    Leave a comment:


  • David Roberts
    replied
    This is a classic case for sticking ' Profile "c:\Life.txt" ' at the end of PBMain. The time saved with John's tip sticks out like a sore thumb.

    Leave a comment:


  • Gösta H. Lovgren-2
    replied
    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
    ======================================================

    Leave a comment:


  • Rodney Hicks
    replied
    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.

    Leave a comment:


  • Gösta H. Lovgren-2
    replied
    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)

    Leave a comment:


  • John Gleason
    replied
    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)

    Leave a comment:


  • Michael Mattias
    replied
    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.

    Leave a comment:


  • Paul Dixon
    replied
    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.

    Leave a comment:


  • Gösta H. Lovgren-2
    replied
    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)
    ==================================

    Leave a comment:


  • Paul Dixon
    replied
    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.

    Leave a comment:


  • Gösta H. Lovgren-2
    replied
    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}

    Leave a comment:


  • Paul Dixon
    replied
    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.

    Leave a comment:


  • Gösta H. Lovgren-2
    replied
    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'

    Leave a comment:


  • Paul Dixon
    replied
    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.

    Leave a comment:


  • Gösta H. Lovgren-2
    replied
    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.

    Leave a comment:


  • Paul Dixon
    replied
    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

    Leave a comment:


  • David Roberts
    replied
    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

    Leave a comment:


  • Paul Dixon
    replied
    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.

    Leave a comment:


  • Paul Dixon
    replied
    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

    Leave a comment:


  • Mel Bishop
    replied
    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.

    Leave a comment:

Working...
X