High resolution cross platform timer...

closed account (z05DSL3A)
I have some old code that I use for ad hoc profiling of algorithms. It is Microsoft/Windows specific and uses the CPU Time Stamp Counter (maybe Intel CPU specific, haven't checked). I would like to have a more protable version of this, but before I spend time on researching this I was woundering if anyone already had somthing that they are willing to share.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/*****************************************************************************\
|     This program is distributed in the hope that it will be useful,         |
|     but WITHOUT ANY WARRANTY; without even the implied warranty of          |
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                    |
\*****************************************************************************/

#define STRICT
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <iostream>

/*****************************************************************************\
The Time Stamp Counter is a 64-bit register present on all x86 processors 
since the Pentium. It counts the number of ticks since reset.
\*****************************************************************************/
inline unsigned __int64 GetCycleCount()
{
    _asm _emit 0x0f
    _asm _emit 0x31
}

class Timer
{
    unsigned __int64 start_cycle;
public:
    unsigned __int64 overhead;
    
    Timer()
    {
        overhead =0;
        Start();
        overhead = Stop();
    }

    void Start()
    {
        start_cycle = GetCycleCount();
    }

    unsigned __int64 Stop()
    {
        return GetCycleCount() - start_cycle - overhead;
    }
};

/*****************************************************************************/
int main()
{
    Timer timer;

    timer.Start();
    Sleep(1000);
    unsigned cpu_speed = (unsigned) (timer.Stop()/100000);
    
    std::cout << "Timer overhead: " << timer.overhead << \
              " clock cycles." << std::endl; 

    std::cout << "CPU Spped: " << cpu_speed/10 << "." << \
              cpu_speed%10 << " MHz." << std::endl;

    return 0;
}
Timer overhead: 285 clock cycles.
CPU Spped: 2415.4 MHz.
Don't have an answer for you, but I can say two things:

1) the tsc is intel specific;
2) the tsc cannot/should not be used for high precision timing according to intel.

The reason for #2 is that on mobile processors and most newer processors that do dynamic cpu frequency scaling,
the tsc does not increment at a constant rate.

You might check into using the HPET instead. On Linux, it is accessed via clock_gettime(), but I don't know about other OSes.
closed account (z05DSL3A)
Thanks,

After a quick look round
clock_gettime for Linux
QueryPerformanceCounter for Windows
mach_absolute_time for Mac

PITA
The Boost Chrono library (still under development) aims to provide portable access to system timers: http://svn.boost.org/svn/boost/sandbox/chrono/libs/chrono/doc/html/index.html

It is the basis for the part of the new C++ standard: http://www2.research.att.com/~bs/C++0xFAQ.html#std-duration

Here's sample C++0x code (which works under GCC 4.4 and should work with newer VS):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <chrono>
#include <iostream>

int main()
{
    auto start = std::chrono::high_resolution_clock::now();
    std::cout << "Starting..." << std::flush;
    auto end = std::chrono::high_resolution_clock::now();
    std::cout << " done." << std::endl;
    double d = std::chrono::duration<double>(end - start).count();
    std::cout << "Time: " << d << " seconds" << std::endl;
    return 0;
}
closed account (z05DSL3A)
That's good to know. :0)
Topic archived. No new replies allowed.