Skip to main content
GameDev.net gamedev.net
🔒 Locked

QueryPerformanceCounter AthlonX2

Started by andor Jan 18, 2006 at 12:43 AM 8 replies 4.6k views
Original Post
andor
andor
I recently upgraded my machine up to an Athlon64 X2 processor, and discovered to my much annoyance, that QueryPerformanceCounter no longer works properly at all. Apparently, I'm not the only one who's discovered this: http://devforums.amd.com/index.php?showtopic=416 Perhaps the easiest way to show what's happening, is to post this snippet from my log. Each frame I wrote out what the frame time was. Frequency: 2002580000 Timer: 0.00871690768908109 NewTickCount: 36147969222589 LastTickCount: 36147951766284 Timer: 0.00872693725094628 NewTickCount: 36147986698979 LastTickCount: 36147969222589 Timer: 0.0375251740255071 NewTickCount: 36148061846142 LastTickCount: 36147986698979 Timer: -0.0197190838817925 NewTickCount: 36148022357099 LastTickCount: 36148061846142 Timer: 0.00889879405566819 NewTickCount: 36148040177646 LastTickCount: 36148022357099 Now, if you'll observe, immediately before the time becomes negative for that frame (yikes!), the frame time jumps up about 4x to what it normally is. This of course, totally screws up the smoothness of my animations and physics, making them leap forwards and then backwards. The typical cycle for this happening is about every 15 frames or so. Also interestingly enough, if you add together that larger time and the negative time and divide by 2, you get 0.0089030450718573, which is within 0.00002 seconds of the other times or so. Additionally, in another test, I called QueryPerformanceFrequency every frame as well, and it always returned the same number. So that's at least constant. I've verified that my timer is only being updated once per frame by also inserting in lines into my log whenever I begin rendering a new frame. I've also tried setting the affinity of my game's thread to a single core, and that didn't help any. This same effect happens, if I strip out my timer and put it into a tiny program that just displays the times returned by looping a bunch of times. So it isn't anything in the rest of my game causing this. My code works flawlessly on my old Athlon 2200+, and works on a hyperthreaded P4. Reading through the Game Timing and Multicore Processors article http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/Game_Timing_and_Multicore_Processors.asp didn't provide any insights either into what the problem is. It states, "This article suggests a more accurate, reliable solution using the Windows QueryPerformanceCounter and QueryPerformanceFrequency APIs.", which is exactly what I am using. I haven't tried the shim to force my game to run on a single-processor yet, as one of the main reasons that I bought this processor was to multi-thread my game engine. The other timers like Environment.TickCount and GetTickCount simply don't provide me with a fine enough timing resolution, being limited to updating every 15ms or so. And that RDTSC instruction sounds far too unreliable and outdated (plus I'm not even sure if there's any sort of nice direct way to use assembly in .net, other than compiling up a c++ dll and using it, though that seems massively overkill for a single assembly instruction). So, have any of you encountered this problem? Or can any of you recommend a different high performance counter that'll work on my processor? At the very least, this is a heads up for any of you also considering getting yourself one of those processors. I'll have to content myself in the mean time by doing some sort of averaging trick with the times when I see one jumping upwards suddenly (though sadly that can be normal game behavior)
Dean Harding
Dean Harding
QueryPerformanceCounter has always been very unreliable on SMP systems. There's two solutions, the first is easy, the second is hard.

1. Use timeGetTime instead. You can call timeBeginPeriod(1) to increase the resolution. I would also recommend calling timeEndPeriod whenever your game loses focus and timeBeginPeriod when it get focus back again - just makes it a little friendlier.

2. Write some logic into your timer to "smooth out" the values returned. Basically this just involves averaging out the values over a period of time. This is a little harder than just switching APIs, but may give more accurate results.
Kitt3n
Kitt3n
Funny how people in the last x threads about timing always tell to
use QueryPerformanceCounter - because microsoft advises not to use
rdtsc and the qpc is fixed it in some patch for windows xp.
In 2 - 3 years, when nobody has windows 2000 anymore and everyone
installed the xp-patch, then is probably a good time to use it - imho :)

Anyway, at the moment I'm the rdtsc timer - on systems ranging from
single-cpu, dual-core amd and intel-ht without any problems.
http://www.gamedev.net/community/forums/topic.asp?topic_id=367833

There are also some other timers you could use (search for it - there
are lots of threads with simular problems) which might help, like
http://www.gamedev.net/community/forums/topic.asp?topic_id=368417
http://www.gamedev.net/community/forums/topic.asp?topic_id=369437


Regards
visit my website at www.kalmiya.com
Spoonbender
Spoonbender
If you search a bit, there's a MSDN KB article about it.

Anyway, the third method (what the end-user does if he ends up with the problem), is to just set the cpu affinity for the process so it runs on the same core all the time.

By the way, timeGetTime is good down to 1ms accuracy. If you got 15, you were doing something wrong (forgot the begin/end-period calls? Although I get 1ms without them)
getTickCount is hopeless though... [wink]
gjaegy
gjaegy
Did you used the SetThreadAffinityMask() function to set which processor should be used ?

I have had lots of problem with the performance counter causing jerky movements, even on single processor machines. The solution I came with was to smooth the time elapsed by avering the 10 last values returned. As suggested before...
Gregory Jaegy[Homepage]
andor
andor
Quote:
Original post by Dean Harding
QueryPerformanceCounter has always been very unreliable on SMP systems. There's two solutions, the first is easy, the second is hard.

1. Use timeGetTime instead. You can call timeBeginPeriod(1) to increase the resolution. I would also recommend calling timeEndPeriod whenever your game loses focus and timeBeginPeriod when it get focus back again - just makes it a little friendlier.

2. Write some logic into your timer to "smooth out" the values returned. Basically this just involves averaging out the values over a period of time. This is a little harder than just switching APIs, but may give more accurate results.


By itself, the timeGetTime method isn't accurate or precise enough for my needs. I'll have to check out that timeBeginPeriod stuff and see if that helps any.

My current plan, was to do an averaging type thing to smooth out my time values. Since there's always that one jump upwards in time before the negative one, I simply need to replace any times that deviate from the last 5 timings or so with their average.
andor
andor
Quote:
Original post by gjaegy
Did you used the SetThreadAffinityMask() function to set which processor should be used ?

I have had lots of problem with the performance counter causing jerky movements, even on single processor machines. The solution I came with was to smooth the time elapsed by avering the 10 last values returned. As suggested before...


I've tried the SetThreadAffinityMask() function, and it didn't make any difference at all.
KulSeran
KulSeran
You may also want to have a look here:
http://www.gamedev.net/community/forums/topic.asp?topic_id=358984
for a post on your exact problem.

Personally I found the only working solution to be a setafinity mask on my timer thread.
Shadowdancer
Shadowdancer
You could look here and look for "usepmtimer".

By default, QPC is still using the TSC, but setting this boot option should make it use the ACPI power management timer, which is independent from pretty much anything the CPU does.
andor
andor
Quote:
Original post by Kitt3n
Funny how people in the last x threads about timing always tell to
use QueryPerformanceCounter - because microsoft advises not to use
rdtsc and the qpc is fixed it in some patch for windows xp.
In 2 - 3 years, when nobody has windows 2000 anymore and everyone
installed the xp-patch, then is probably a good time to use it - imho :)

Anyway, at the moment I'm the rdtsc timer - on systems ranging from
single-cpu, dual-core amd and intel-ht without any problems.
http://www.gamedev.net/community/forums/topic.asp?topic_id=367833

There are also some other timers you could use (search for it - there
are lots of threads with simular problems) which might help, like
http://www.gamedev.net/community/forums/topic.asp?topic_id=368417
http://www.gamedev.net/community/forums/topic.asp?topic_id=369437

Regards


Just tried that patch for XP, and it works perfectly now. So, that seems to be the ideal solution.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.