• Advertisement
Sign in to follow this  

Anyone having issues with Dual Core CPUs and timers?

This topic is 4161 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

I have a dual core cpu and my timer works fine until I move around a bit and then it goes crazy? I not sure where to start with this. I am using the following functions QueryPerformanceCounter(&framedelay); QueryPerformanceFrequency(&tickspersecond); Thanks

Share this post


Link to post
Share on other sites
Advertisement
There are tones of posts about this ever since the AthlonX2 cores came out.

The problem is the two cores have seperate clocks, so using the high performance counters will cause errors, as each core
returns a slightly different value.

There are several fixes.
-Some people manage to get the patches from AMD and MS to work. (I didn't :( ) These are the new drivers for cool-and-quiet and a patch for QPC.
-You can force the thread that is runnning the timing code to run on only one core by setting the affinity of that thread to only the first CPU.
-You can get a program like WinlauncherXP, and use it to force the afinity for you(good for retail programs that have problems, like COD2).

Share this post


Link to post
Share on other sites
You can force the thread that is runnning the timing code to run on only one core by setting the affinity of that thread to only the first CPU.

This sounds good, but I have never done this before. So is there some function call for this? e.g. SetProcessorAffinity() GetProcessAfinity()?

thanks

Share this post


Link to post
Share on other sites
There's also SetProcessAffinity(), which locks the affinity for an entire process.

However, the right solution is to get the patches from MS and AMD to work. I had no problems with that, and I don't know anyone who did, so it's clearly possible.

QueryPerformanceCounter() is intended to be the reliable, bug-free, cheap counter you can use, now that RDTSC is discouraged. The continual bugs with that call (first the jump-ahead-4-seconds bug, then the jump-ahead-1.3-seconds bug, and now the dual-core bug) is doubly unfortunate.

Share this post


Link to post
Share on other sites
for a game use a different method of querying the number of ticks under windows
iirc something like either
timeGetTime()
getTickCount();

theres no need for such a high resolution timer (this is only needed if u wanna test a func etc + see how long it takes)

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
When one runs into these sorts of problems, it can be most beneficial to check the Help and Support section of MS's site. Upon searching, I've come across the following two pages:

http://support.microsoft.com/kb/327809/en-us

http://support.microsoft.com/kb/909944/en-us

And yes, this is a well known issue.

Share this post


Link to post
Share on other sites
Well I tried the __int64 variable and still a no go. One of the MSDN posts said to use __int64...



__int64 tickspersecond;
__int64 currentticks;
__int64 framedelay;

void Timer::Init(float tfps)
{
targetfps = tfps;
QueryPerformanceCounter((LARGE_INTEGER *) &framedelay);
QueryPerformanceFrequency((LARGE_INTEGER *) &tickspersecond);
}

void Timer::SetSpeedFactor(void)
{
QueryPerformanceCounter((LARGE_INTEGER *) &currentticks);
//This frame's length out of desired length
//speedfactor = (float)(currentticks.QuadPart-framedelay.QuadPart)/((float)tickspersecond.QuadPart/targetfps);
speedfactor = float(currentticks - framedelay) / float(tickspersecond / targetfps);
fps = targetfps/speedfactor;
if(speedfactor <= 0)
speedfactor = 1;

framedelay = currentticks;
}




still no dice

[Edited by - MARS_999 on August 15, 2006 3:08:14 AM]

Share this post


Link to post
Share on other sites
LARGE_INTEGER is essentially just a wrapper around __int64, so swapping one for the other won't help at all. You should either install the patches or use SetThreadAffinityMask to force the timer thread onto one processor.

Personally, I use the SetThreadAffinityMask method, since I know that otherwise if I release an app using QPC(), someone will complain that it doesn't work and that it's "my fault" for not fixing it somehow.

Share this post


Link to post
Share on other sites
Quote:
Original post by Evil Steve
LARGE_INTEGER is essentially just a wrapper around __int64, so swapping one for the other won't help at all. You should either install the patches or use SetThreadAffinityMask to force the timer thread onto one processor.

Personally, I use the SetThreadAffinityMask method, since I know that otherwise if I release an app using QPC(), someone will complain that it doesn't work and that it's "my fault" for not fixing it somehow.


Thanks for the reply Evil Steve, so how does your code look for SetThreadAffinityMask then if you don't mind me asking... Thanks

Share this post


Link to post
Share on other sites
Quote:
Original post by MARS_999
Thanks for the reply Evil Steve, so how does your code look for SetThreadAffinityMask then if you don't mind me asking... Thanks
Just in my main thread:
SetThreadAffinityMask(GetCurrentThread(), 0x01);

I think anyway, I don't have my code with me.

Share this post


Link to post
Share on other sites
Quote:
Original post by hplus0603

However, the right solution is to get the patches from MS and AMD to work. I had no problems with that, and I don't know anyone who did, so it's clearly possible.



Actually, the right solution is to set the thread affinity. You cannot rely on your customers to be patched correctly.
Do not use the SetProcessAffinity unless you don't want your application taking advantage of the dualcore performance enhancements, just use SetThreadAffinityMask and make sure your counter runs on its own thread.

Share this post


Link to post
Share on other sites
Quote:
just use SetThreadAffinityMask and make sure your counter runs on its own thread.

huh, that sounds not exactly lightweight. So does your get_time() API send a message to the timer thread and wait for an answer?

Share this post


Link to post
Share on other sites
That's not what he meant - you don't have a thread that runs your timer and nothing else; you just run your timer in the same thread that needs being timed.

A better way to say it is that every thread that checks timings needs to maintain its own timer variables internally, and set its own processor affinity mask. If you're willing to do a little work, you can even check for multiple processors, and set up the affinities so that your threads are more evenly distributed across the available CPUs.

Share this post


Link to post
Share on other sites
Quote:
Original post by bit64
Actually, the right solution is to set the thread affinity. You cannot rely on your customers to be patched correctly.

Sure you can, its done all the time. Pick any random game, and I'll bet they suggest updating your video card drivers if you experience problems.

CM

Share this post


Link to post
Share on other sites
Quote:
you just run your timer in the same thread that needs being timed.
A better way to say it is that every thread that checks timings needs to maintain its own timer variables internally, and set its own processor affinity mask.

Timer state in TLS? Interesting.
Doesn't sound too safe, though - if 2 threads (UI and main engine) have some timestamp they need to agree on, you are back to square 1.

Quote:
If you're willing to do a little work, you can even check for multiple processors, and set up the affinities so that your threads are more evenly distributed across the available CPUs.

hoo boy, sounds dangerous. You need to take HT into account, else your game will run like a dog when you farm out worker threads to every single virtual 'CPU'. You have therefore committed yourself to releasing patches for all future CPU changes (e.g. when AMD adds something like HT).

Also, if user is burning a CD while playing your game (now quite viable with dual core), you potentially mess that up for him. Probably better to let OS take care of scheduling!

Share this post


Link to post
Share on other sites
Perhaps I should be more clear. When I say that you should make sure that your timer calls are on their own thread, I mean that the differences between SetProcessAffinity and SetThreadAffinity are only remarkable if your application has more than one thread! Simple as that.

Calling SetProcessAffinity on a multithreaded application will kill any advantage you would have of running on a dual core CPU.


Share this post


Link to post
Share on other sites
Slight problem that on Windows XP x64 uses the server kernel, QueryPeformance* functions will use the time stamp counters (rdtsc). (At least it did at the time when it was in beta). Also, the HPT timers are relatively expensive to use (not that you have too much options). There is an excellent article on gameDev's (see resources) on timing in windows.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Quote:
Original post by zedzeek
for a game use a different method of querying the number of ticks under windows
iirc something like either
timeGetTime()
getTickCount();

theres no need for such a high resolution timer (this is only needed if u wanna test a func etc + see how long it takes)


Errrr, wrong. timeGetTime can be quite off. If you want decent animation you need very precise time. Not something 1-2ms off. Well, maybe you do, but not me.

Share this post


Link to post
Share on other sites
Quote:
Original post by Conner McCloud
Quote:
Original post by bit64
Actually, the right solution is to set the thread affinity. You cannot rely on your customers to be patched correctly.

Sure you can, its done all the time. Pick any random game, and I'll bet they suggest updating your video card drivers if you experience problems.

Going to have to disagree with you on this one. The nature of this glitch is such that it's often left unpatched as a means of gaining an unfair speed advantage in the game Planetside, to name an example. Sure, that's due to shoddy netcode in no small way, and isn't without it's detremints, and really isn't THAT much of a game breaker, but it's enough to severely piss off a large segment of their customer base - and not the ones who's own dumb fault it is, either.

Share this post


Link to post
Share on other sites
Quote:
Original post by DaBookshah
Quote:
Original post by hplus0603
.....RDTSC is discouraged....


Why?


If I remember right because multicore cpus have different timers that may not be in sync (basically the main cause of the problems mentioned in this thread). Also if the cpu throttles speed(I think they are all capable of it now days), then you times no longer match reality. For instance SW:KtoR, would play at a different speed on my laptop if I unplugged the power (which throttle the cpu to 600 from 100 MHz) while playing. I think the only good use of rdtsc is to measure the number of cycles a piece of code uses. Assuming you set the affinity and took the minimum cycles of numerous test to help remove problems from windows changing the threads.

Also x64 installs (A least I think mine did) with /usepmtimer in the boot.ini so it's not supposed to use rdtsc for QPC. That option may have been enabled by a patch too (I didn't see it until my system was fully patched up).

Share this post


Link to post
Share on other sites
Now that's nice.. I read this thread yesterday and suddenly I realized why Neverwinter Nights didn't work correctly on my computer. It's patched up with all the latest patches and I thought I had the newest amd patched but after (re)installing the latest amd patches it worked great!

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement