QueryPerformanceCounter behaves erratically on a multicore processor under Windows 10

On Windows, my application uses QueryPerformanceCounter

(s QueryPerformanceFrequency

) to perform a high resolution timestamp.

Since Windows 10 (and has only been tested on Intel i7 processors so far), we see erratic behavior in the values ​​returned QueryPerformanceCounter

. Sometimes, the value returned by the call jumps forward and then reverts to its previous value. It seems like the thread has moved from one core to another, and after the time has elapsed, a different counter value was returned (no evidence, just gut feel).

This has never been seen in XP or 7 (no data on Vista, 8 or 8.1).

The "easy" option is to activate the bootable UsePlatformClock opiton with BCDEdit (which makes everything erroneous).

I am aware of the potentially superior GetSystemTimePreciseAsFileTime

, but as we still support 7, this is not really an option unless we write completely different codes for different OSes, which we really don't want to do.

Is this behavior observed / explained in Windows 10?

+3


source to share


1 answer


I need a lot more knowledge about your code, but let me highlight a few things from MSDN:

When calculating deltas, the values ​​[from QueryPerformanceCounter] must be pinned to ensure that any errors in the time values ​​do not result in time-related crashes or unstable computations.

And especially this:

Set one thread to stay on one processor using Windows SetThreadAffinityMask ... Although QueryPerformanceCounter and QueryPerformanceFrequency are typically configured for multiple processors, errors in BIOS or drivers can cause these routines to return different values when a thread moves from one processor to to another. Therefore, it is best to keep the thread on a single processor.

In your case, one of these errors can be exploited. Shortly speaking:

  • You should always request the timestamp from one thread (setting the same affinity to the cpu to make sure it doesn't change) and read that value from any other thread (just a blocked read, no fancy syncs needed).
  • Freeze the calculated delta (at least make sure it is not negative) ...

Notes:

QueryPerformanceCounter()

uses TSC if possible (see MSDN ). The TSC sync algorithm (if available and in your case it should be) has changed significantly from Windows 7 to Windows 8, however please note:



With the advent of multi-core / hyper-threaded processors, multi-processor systems and dormant TSC operating systems, accurate results cannot be relied upon - unless great care is taken to correct possible flaws: speed and whether all cores (processors) have the same values ​​in their timing registers ... There is no promise of synchronizing the synchronized counters of multiple processors on a single motherboard. Thus, a program can only get reliable results by limiting itself to running on one specific processor .

Then, even if the QPC is monotonic in theory, you should always call it from the same thread to be sure.

Another note, if synchronization is done using software, you can read from Intel documentation that:

... It can be difficult for a program to do this in such a way as to ensure that all logical processors have the same value for the TSC at a given time ...


Edit : If your application is multithreaded and you can't (or don't want to) to set the processor affinity (especially if you need an accurate timestamp due to having synchronized values ​​between threads), then you can use GetSystemTimePreciseAsFileTime()

when running on Win8 ( or later) and revert to timeGetTime()

for Win7 (after you set the granularity to 1ms with timeBeginPeriod(1)

and assuming 1ms is sufficient). Very interesting reading: The Timestamp Windows Project .

Edit 2 : directly suggested by the OP! This, when applicable (because it is a system setting and not local to your application), can be an easy way. You can force QPC to use HPET instead of TSC with bcdedit (see MSDN ). The latency and resolution should be worse, but they are intrinsically safe compared to the problems described above.

+2


source







All Articles