Measure CPU frequency (x86 / x64)
Asked Answered
B

3

6

I'm looking for some kind of a library that gives me accurate CPU frequency values periodically on both Intel and AMD processors, on 32-bit and 64-bit Windows.

The purpose of this is to accuratly measure CPU load on a given computer. The problem is that calling QueryPerformanceCounter() returns clock ticks (used to measure the duration of an activity) but the underlying CPU frequency is not constant because of SpeedStep or TurboBoost. I've found several computers where turning off SpeedStep / TurboBoost in the BIOS and doesn't prevent CPU frequency scaling based on load.

I'm trying to see if there are any libraries available that could be used to detect CPU frequency changes (much like how Throttlestop / CPU-Z or even the Overview tab of Resource Monitor in Windows 7) so that I could query and save this information along with my other measurements. Performance counters don't seem to return reliable information, as I have computers that always return 100% CPU frequency, even when other tools show dynamic frequency changes.

I searched for such libraries but most results come back with gadgets, etc., that are not useful.

Blow answered 8/5, 2012 at 19:0 Comment(1)
For reliable results you need to read the cpu frequency directly from the cpu. That's the way CPU-Z etc. do it. While current Linux/Windows give some cpu statistics (like /proc/cpuinfo), which contain some frequency, this does often not take turboboost/overclocking etc. into account.Cordiform
C
8

You can combine a high-resolution timer with a clock cycle counter to compute the current clock rate. On modern CPUs, the cycle counter can be read with this function:

static inline uint64_t get_cycles()
{
  uint64_t t;
  asm volatile ("rdtsc" : "=A"(t));
  return t;
}

Note that this is per CPU, so if your program gets moved around CPUs, you're in trouble. If you know about CPU pinning techniques on your platform, you might like to try those.

For high resolution time measurement, you can use the tools in <chrono>; here's a semi-useful post of mine on the topic.

Club answered 8/5, 2012 at 19:9 Comment(6)
@Kerrer SB: thanks for your answer but I can't understand what your code does - I'm not familiar with the syntax you used for the assembly bit. Is this VC++ syntax or something else?Blow
@Blow It's gcc inline assembly.Cordiform
@drhirsch: Thank you. I assume the "=A" bit means store the return value of RDTSC in t.Blow
@Blow Saying that, any answer here which involves using the TSC will most likely not work - on newer CPUs the rate at which the TSC runs is fixed and independent of the actual CPU frequency.Cordiform
@drhirsch: Do you know what it means "newer CPU-s"? My problem is that I potentially need this information on computers that are 3+ years old. If fixed-frequency TSC was used around 2008, it's likely all right, I can probably rely on it but if it's just a recent addition (which is how it seems to me based on reading), it's not really a solution. Also, is there a way to control what CPU is checked when RDTSC is called?Blow
Older Athlon X2+ and first generation Core2 didn't have synchronized TSC, which was a cause for major timing problems in some games. After that I am not sure, google for it, or just try.Cordiform
A
1

Try to focus on what you are trying to do, and not on how to do it.

What is your ultimate goal?

If, as you say, you are trying to "measure CPU load on a given computer", on Windows it may be a good practice using "PdhOpenQuery" and the "Pdh*" family functions.

See this SO answer as well:

How to determine CPU and memory consumption from inside a process?

Appendicitis answered 8/5, 2012 at 19:23 Comment(3)
I posted a link to Performance Counters too, but then I saw that the question claims the measurements are not good enough.Humblebee
@friol: thanks, but the Pdh* functions all return performance counter information which are all unreliable. The SO link is also not useful to me - GetProcessTimes() returns time durations but it doesn't tell me at what frequency the CPU was running during that time. If the CPU is running at 10% for 60 milliseconds and then 45% for another 60 milliseconds, obviously the second load is higher, yet I'll get 10 milliseconds in both cases.Blow
@GregInozemtsev: yes, unfortunately, % of Maximum Frequency gives me incorrect values (100% on computers where we clearly have frequency changes). I don't know if any other counter would give me correct data, but the ones I tried didn't work reliably. The above counter works fine on my Windows 7 laptop but not on some of my servers.Blow
F
1

Consider looking at the __rdtsc intrinsic function (#include "intrin.h" in Visual Studio).

This yields the clock count directly from the processor via the x86/x64 function RDTSC (Read Timestamp).

Falter answered 10/5, 2012 at 8:47 Comment(2)
thank you, others also suggested this. My understanding is that even this instruction may be affected by power management-related frequency changes, so it's unreliable. Am I wrong in this?Blow
RDTSC returns the value of the clock counter on the processor at the time when it is accessed in the pipeline. If you need super-fine-grained timestamp control you'll need to perform a serializing instruction before the RDTSC. After that, this is the most fine-grained clock counter available on your machine.Falter

© 2022 - 2024 — McMap. All rights reserved.