Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

Ademan555

Best, most accurate clock?

This topic is 5218 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Ok, ive done a little bit of digging for timing in c++, and a report i read said that the multimedia clock (it must be in mmsystem.h ) is the most accurate, does anyone have any input? its not as if i need super accurate timing for my crappy 2d engine... but i was hoping to create a class and save it for later, once im better at d3d and c++ -Dan Yes I realize im a n00b... Don't yell. -fel [edited by - felisandria on December 12, 2003 2:22:23 PM]

Share this post


Link to post
Share on other sites
Advertisement
they are probably refering to QueryPerformanceCounter, (although i dont think that needs winmm, maybe timeGetTime).

Regardless, using an intel system:
__asm {
cpuid ; force all previous instructions to complete
rdtsc ; read time stamp counter
mov time, eax ; move counter into variable
}
Should give you a reading as accurate as possible. It is sometimes advised to do this reading twice, and you will need to look up your processors manual to see how many clock ticks the rdtsc instruction takes (about 30 from memory)

Share this post


Link to post
Share on other sites
quote:
Original post by aboeing
they are probably refering to QueryPerformanceCounter, (although i dont think that needs winmm, maybe timeGetTime).

Regardless, using an intel system:
__asm {
cpuid ; force all previous instructions to complete
rdtsc ; read time stamp counter
mov time, eax ; move counter into variable
}
Should give you a reading as accurate as possible. It is sometimes advised to do this reading twice, and you will need to look up your processors manual to see how many clock ticks the rdtsc instruction takes (about 30 from memory)


Shouldn''t matter how many it takes.. because if it takes 30, it will ALWAYS be behind by 30, therefore your program will see the start time 30 ticks after it really is, etc... so it will always give the same time change value!

if it goes from 0 -> 600... or 30 -> 630 if you add the 30 in.. the time difference is still identical, so no need to compensate!

Share this post


Link to post
Share on other sites
If the counter returns the timestamp BEFORE it was executed, you would have the overhead of this instruction before executing your code. If the counter returns the timestamp AFTER it's been executed (sounds strange), you would have overhead when reading the time after your code has executed..
Either way you have the overhead of 1 timestamp read...

-- EDIT --
This is if you're using it for performance measurement obviously (wouldn't reckon you'd use the timestamp counter for anything else..)

[edited by - BiTwhise on December 12, 2003 10:18:18 AM]

Share this post


Link to post
Share on other sites
timeGetTime is probably fine for your needs, but it''s not the best. It has a resolution of 1 ms on 9x platforms, and also on NT if you call timeBeginPeriod; note that doing so increases system load. The problem is, it''s basically just a tick counter (incremented every timer interrupt, as reported by GetSystemTimeAdjustment), and drifts over time (the interrupt isn''t always delivered on time) - this is bad if you''re relying on this clock for multiplayer.

QueryPerformanceCounter has better resolution (depending on HAL, ~1 µs if using PIT, ~.3 µs for the PM timer, better than 100 ns if HPET is available, or CPU clock period if using TSC), but a raft of problems:
[comments from timer source]
// problems:
// - multiprocessor systems: may be inconsistent across CPUs;
// setting thread affinity is too much work.
// - if implemented with TSC: same problems as above.
// (we check if TSC/QPC freqs differ by more than 10% -
// can''t assume PIT / PMT freq values, because new the new HPET
// timer''s frequency is unspecified)
// - Q274323: jumps several seconds under heavy PCI bus load.
// readings are checked against system time and discarded if invalid.
// - "System clock problem can inflate benchmark scores":
// invalid value if not polled every 4.5 seconds? solved
// by calibration thread, which reads timer every second anyway.

While we''re at it, problems with rdtsc / the CPU timestamp counter:
// problems:
// - multiprocessor systems: may be inconsistent across CPUs;
// setting thread affinity is too much work.
// - deep sleep modes: TSC may not be advanced.
// - SpeedStep/''gearshift'' CPUs: frequency may change.
// this happens on notebooks now, but eventually desktop systems
// will do this as well (if not to save power, for heat reasons).
//
// detect''s tsc_is_safe check tries to ensure the above won''t happen,
// but I don''t think it''s possible to determine beforehand if the CPU
// does SpeedStep (currently, it assumes so iff running on a laptop).
// to be safe, wsdl disables the TSC when an APM message is received.

What I do (to emulate gettimeofday on Windows; Linux does something similar already) is choose one of 3 high-resolution timers (QPC, TSC, timeGetTime), depending on which has the least problems, and lock it to the system time. Still working on it, but looks good already.

aboeing:
In addition to the above problems, be sure to issue several cpuid before first use of the timer - the first few times take longer to execute. BTW, the CPU clock isn''t terribly accurate.

Share this post


Link to post
Share on other sites
I think the standard C function clock works well, to use it I include:
#include <ctime>
#include <cstdlib>

In school I program in Windows and submit my homework on NetBSD, and one of them doesn''t have CLOCKS_PER_SEC defined (not sure which constant is the standard), so I keep this up top:

#ifndef CLOCKS_PER_SEC
#define CLOCKS_PER_SEC CLK_TCK
#endif

to time something:

std::clock_t end_time, start_time;
start_time = std::clock();
//do something here
end_time = std::clock();
double elapsed_time_in_clock_ticks = (double)(end_time - start_time);
double elapsed_time_in_seconds = elapsed_time_in_clock_ticks / (double)CLOCKS_PER_SEC;


And unlike those windows functions, if you ever want to port your code, this code is platform independent :-)

Share this post


Link to post
Share on other sites
Unfortunately, clock() only has a resolution of 10..15 ms on Windows (it''s implemented with GetSystemTimeAsFileTime).

> And unlike those windows functions, if you ever want to port your code, this code is platform independent
Yes - which is why I emulate gettimeofday and clock_gettime on Windows, and use those in real code

Share this post


Link to post
Share on other sites
quote:
Original post by Ready4Dis
if it goes from 0 -> 600... or 30 -> 630 if you add the 30 in.. the time difference is still identical, so no need to compensate!

Yes, but thats only because I''m an idiot.
I really should stop posting late at night.
quote:

be sure to issue several cpuid before first use of the timer - the first few times take longer to execute.
BTW, the CPU clock isn''t terribly accurate.


Yeah, this is basically what AMD suggested to do to count ticks. What other possible method will give you a better reading?
I thought rdtsc was the most accurate reading possible, the only reason you get inaccuracies is because of multitasking?

Share this post


Link to post
Share on other sites
read the cedar.intel.com documentatino for rdstc.


Second poster was correct.

What they do is to time their own function after three warm up passes.


RDTSC WITH CPUID is about 20 something clock ticks.

Just subtract it from your time differences if that''s what you are after (as in a timer). Same as any other method for overhead.


As a note: QueryPerformanceCounter is about 674 clock ticks.

That''s for a straight
//start
QueryPerformanceCounter(&starttime);
QueryPerformanceCounter(&endtime);
totaltime=endtime-starttime;
//end


For overhead, use declspec(naked) if you know what you are doing. You won''t get any extra overhead that way.


Btw Dan, don''t geel like a "n00b" because you asked for help on a topic like this. You did your research, and it''s one of the most reasonably debated topics around here. Also a pretty important one for some applications.

It kind of comes down to preference. I still like using QueryPerformanceCounter for things like frame rate and testing large blocks of code as it saves the inline assembly. For smaller peices (testing which is faster etc for release modes) and optimisation I use the RDTSC code.

Oh, as a side note: CPUID isn''t really necessary for the newer processors, but use it anyway unless that extra 15 or so clock ticks is that important to you. Better safe than sorry.

Share this post


Link to post
Share on other sites
> I thought rdtsc was the most accurate reading possible, the only reason you get inaccuracies is because of multitasking?
I''m saying it''s not as accurate as it would appear - the crystal that drives the CPU clock isn''t the best. The TSC is the best you''ve got for measuring short intervals, but you''re screwed if the processor decides to sleep, or change frequency. I think the OP wanted a wall clock reference - in that case, using the TSC is a lot of work

> As a note: QueryPerformanceCounter is about 674 clock ticks.
Wow, that''s fast - sounds like a switch to kernel mode, rdtsc, a little bit correction, and that''s it. The other QPC implementations (PIT, PMT, HPET) require port I/O, so it ends up taking several µs. What OS and HAL is this on?

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!