Results 1 to 9 of 9

Thread: A high precision timer

  1. #1
    Expert
    Matt Mahoney's Avatar
    Join Date
    May 2008
    Location
    Melbourne, Florida, USA
    Posts
    3,255
    Thanks
    306
    Thanked 779 Times in 486 Posts
    I wrote a timer function for counting CPU clock cycles for very precise timing when doing optimization (under 1 ns). Use it like this:

    Code:
     
      int start = rdtsc();  // get the time 
      // code to be timed 
      printf("%u clocks\n", rdtsc()-start);  // print time difference


    Here is the function:
    Code:
     
    unsigned int(*const rdtsc)()=(unsigned int(*)())(char*)"\x0f\x31\xc3";


    The 3 byte string is x86 assembler for

    RDTSC
    RET

    The x86 has a 64 bit counter that is incremented once per clock cycle. The RDTSC instruction puts the counter in edx:eax. The function returns the low 32 bits in eax. The code is first cast to char* (so VC++ doesn't complain), then cast to a constant pointer to a function taking no parameters and returning unsigned int.

    The code should be safe (on a Pentium or higher) because eax, edx (and ecx) are scratch registers that don't need to be preserved across function calls. I tested it with g++, Borland, Mars, and VC++ with various optimizations in WinXP. No assembler required

    You could also get all 64 bits of the counter by changing the return type to unsigned long long.

  2. #2

  3. #3
    The Founder encode's Avatar
    Join Date
    May 2006
    Location
    Moscow, Russia
    Posts
    3,985
    Thanks
    377
    Thanked 353 Times in 141 Posts
    Thanks a lot!

  4. #4
    Moderator

    Join Date
    May 2008
    Location
    Tristan da Cunha
    Posts
    2,034
    Thanks
    0
    Thanked 4 Times in 4 Posts
    This will also be of interest to people wanting to use the RDTSC instruction.

    Download RDTSC.7z (50.7 KB)

    Good Luck!

  5. #5
    Expert
    Matt Mahoney's Avatar
    Join Date
    May 2008
    Location
    Melbourne, Florida, USA
    Posts
    3,255
    Thanks
    306
    Thanked 779 Times in 486 Posts
    A little program that prints your CPU clock speed once per second (up to 4 GHz). Ignore the first output.

    Code:
     
    #include <stdio.h> 
    #include <time.h> 
     
    unsigned int(*const rdtsc)()=(unsigned int(*)())(char*)"&#92;x0f&#92;x31&#92;xc3"; 
     
    int main() { 
      int start=0; 
      while (1) { 
        time_t t=time(0); 
        while (t==time(0)); 
        int end=rdtsc(); 
        printf("%u Hz&#92;n", end-start); 
        start=end; 
      } 
    }

    There is a bit of clock variation. I get something like this:

    1342034267 Hz
    2185611538 Hz
    2190199726 Hz
    2188774479 Hz
    2187295626 Hz
    2188892541 Hz
    2190123133 Hz
    2188530729 Hz
    2187155465 Hz
    2190711215 Hz

  6. #6
    Member
    Join Date
    Jun 2009
    Location
    Kraków, Poland
    Posts
    1,475
    Thanks
    26
    Thanked 121 Times in 95 Posts
    matt, you're counting printf delay here. could you try something like that:

    Code:
     
    #include <stdio.h> 
    #include <time.h> 
     
    unsigned int(*const rdtsc)()=(unsigned int(*)())(char*)"x0fx31xc3"; 
     
    int main() { 
      int start; 
      while (1) { 
        time_t t=time(0); 
        while (t==time(0)); 
        time=time(0); 
        int start=rdtsc(); 
        while (t==time(0)); 
        int end=rdtsc(); 
        printf("%u Hz
    ", end-start); 
      } 
    }

    also run program in realtime priority. windows is a multitasking system - it switches programs execution by tens or hundreds times per second.

  7. #7
    Programmer osmanturan's Avatar
    Join Date
    May 2008
    Location
    Mersin, Turkiye
    Posts
    651
    Thanks
    0
    Thanked 0 Times in 0 Posts
    @matt
    I highly recommend that use QueryPerformanceCounter instead of RDTSC. Especially, on laptops which have a power saving technology (such as Intel Speedstep Technology), CPU frequency can be changed. So, timing values can be wrong. Also, you have to know that on multicore systems RDTSC is not reliable for timing. This issues explained in DX SDK. Also, you can check out Intel web site.

    In past, I have implemented a simple game engine which uses high precision timer for interaction timing (such as player movement). While using RDTSC for timing player movement becomes strange. Like a sinusoidal acceleration was achived It was a headache for me. So, I've moved back to QueryPerformanceCounter. But, I don't know a good way for cross-platform solution.
    BIT Archiver homepage: www.osmanturan.com

  8. #8
    Expert
    Matt Mahoney's Avatar
    Join Date
    May 2008
    Location
    Melbourne, Florida, USA
    Posts
    3,255
    Thanks
    306
    Thanked 779 Times in 486 Posts
    Quote Originally Posted by donkey7
    matt, youre counting printf delay here.
    Actually no, because the printf delay is included in the busy loop. The outer loop always takes one second for time() to change, and rdtsc() is called only once.

    I know that rdtsc() is not reliable for real time because processor speed can vary. My Athlon-64 3500+ uses CoolnQuiet so the CPU drops to from 2188 MHz to 995 MHz the processor is idle. I can use rdtsc() to see when this actually happens. The following code adds a Windows Sleep() call inside the busy loop and you can see the CPU speed drop. You can also see that Sleep() has a resolution of 1/64 second.

    <div class=""jscript""><pre>
    #include <stdio.h>
    #include <time.h>
    #include <windows.h>

    unsigned int(*const rdtsc)()=(unsigned int(*)())(char*)"&#92;x0f&#92;x31&#92;xc3";

    int main(int argc, char** argv) {
    int delay=argc>1 ? atoi(argv[1]) : 0; // in ms
    int start=0;
    while (1) {
    time_t t=time(0);
    int slept=0;
    while (t==time(0)) {
    if (delay) Sleep(delay);
    ++slept;
    }
    int end=rdtsc();
    if (start) printf("%u Hz slept %d x %d ms&#92;n",
    end-start, slept, delay);
    start=end;
    }
    }
    [/code]


    C:&#92;tmp>rdtsc 1
    994799764 Hz slept 64 x 1 ms
    994942599 Hz slept 64 x 1 ms
    994814060 Hz slept 64 x 1 ms
    996312765 Hz slept 64 x 1 ms
    993461913 Hz slept 64 x 1 ms
    994919068 Hz slept 64 x 1 ms
    994908950 Hz slept 64 x 1 ms
    994820691 Hz slept 64 x 1 ms
    994941304 Hz slept 64 x 1 ms
    994878264 Hz slept 64 x 1 ms
    994890538 Hz slept 64 x 1 ms
    994801091 Hz slept 64 x 1 ms
    994941645 Hz slept 64 x 1 ms
    ^C

    I get the same clock frequency for any delay of 1 or more ms, and Task Manager shows CPU at 0% (instead of 100%).

    A program like this is useful for measuring CPU clock speed while another program is running. For example, clock speed drops while a compression program waits on disk.

  9. #9
    Expert
    Matt Mahoney's Avatar
    Join Date
    May 2008
    Location
    Melbourne, Florida, USA
    Posts
    3,255
    Thanks
    306
    Thanked 779 Times in 486 Posts
    Another interesting effect is when I run the CPU part of the time like this:

    Code:
     
        if (delay) Sleep(delay); 
        while (t==time(0));  // busy for 1000 - delay ms

    If the delay is 100 ms or less per second (CPU at 90%), then the CPU runs at full speed (2188 MHz) even while asleep. If the delay is 900 ms or more (CPU at 10%) then the CPU runs at low speed (995 MHz) even during the busy loop. If the delay is between 10% and 90% then the CPU speed switches back and forth.

Similar Threads

  1. The best algorithm for high compression
    By Wladmir in forum Data Compression
    Replies: 8
    Last Post: 18th April 2010, 15:54
  2. Timer 3.01 bug
    By Rugxulo in forum The Off-Topic Lounge
    Replies: 7
    Last Post: 31st July 2009, 22:36
  3. Alternative timer
    By Bulat Ziganshin in forum The Off-Topic Lounge
    Replies: 4
    Last Post: 4th July 2009, 04:16
  4. Ross Williams high-speed LZRW compressors
    By LovePimple in forum Data Compression
    Replies: 4
    Last Post: 8th June 2008, 21:26
  5. High Throughput Compression (FPC vs DFCM)...
    By Raymond in forum Forum Archive
    Replies: 0
    Last Post: 5th March 2007, 19:02

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •