1

Currently working on creating a sorts of "task manager" in c#/wpf. I've searched around but haven't found a solution to my problem.

I am trying to retrieve the CURRENT clock speed of one's CPU (not utilization, base, min/max). I have tried using ManagementObjects, but "CurrentClockSpeed" is always giving a fixed value of 3400, or 3.4GHz, which is the stock max speed of the CPU. I have tried many times and it gives me the same answer, so it isn't just a coincidence i think.

    ManagementObject Mo = new ManagementObject("Win32_Processor.DeviceID='CPU0'");
        uint sp = (uint)(Mo["CurrentClockSpeed"]);
        System.Threading.Thread.Sleep(1000);
        sp = (uint)(Mo["CurrentClockSpeed"]);
        Mo.Dispose(); //return and such later in the code

Any suggestions on how to fix this issue (I am not bound to using ManagementObjects, I have OpenHardwareMonitor, and can use other packages if need be) are appreciated.

Clemens
  • 123,504
  • 12
  • 155
  • 268
Aaron
  • 97
  • 12
  • Might be a naive question, but aside from overclocking, why would the speed of the CPU change? "Speed" is how many calculations per time *can* be done, right? Anything else is utilization, which you're not interested in. – Corak Jul 13 '18 at 20:08
  • No worries, it's all a bit confusing! I think what you might be thinking of when speaking on "speed", is what we might call our max clock speed (the GHz manufactures provide when buying a processor). That speed is just telling us the maximum (unless overclocked) speed it should run at, and how fast you should expect it to run. But what I am looking for is the current clock speed. That just tells us the value in GHz at which the processor is communicating. Your clock speed is always going up and down, depending on the load of the CPU, because it does not always need to work at 100%. – Aaron Jul 13 '18 at 20:14
  • "CurrentClockSpeed" seems to be the right property. Mine varies between 2900 and 2901 on this processor I'm currently using. Are you sure yours should be reading lower? – itsme86 Jul 13 '18 at 20:28
  • Hmmm, do you have your code by chance? I am pretty positive. I have run it in different variations, and based it off of task manager. It just returns a base value no matter what, even when the current speed is much lower. – Aaron Jul 13 '18 at 20:30
  • 4
    @Corak `why would the speed of the CPU change?` a number of reasons. one example, modern processors will automatically throttle themselves if overheating is detected, as a means of protecting itself. the OS can also request the processor run at a reduced clock speed to save power. –  Jul 13 '18 at 20:31
  • Have you tried straining the cpu at all? Open up some intensive programs and let them sit for a few minutes and then try cleaning + rebuilding + running the program. Let us know if the number is still the same. – Tom Hood Jul 13 '18 at 20:32
  • I use a different code entirely, and it works for me, but yours should also work fine. Maybe your CPU is always running at max capacity? – Cubemaster Jul 13 '18 at 20:33
  • Could you provide the code? I would like to see how your's is made compared to mine. I checked the current clock speed during tests, and most times, it was not running close to max clock speed. – Aaron Jul 13 '18 at 20:38
  • @user9622460 -- I think you need to re-instantiate the `ManagementObject` between readings. Try the following, and see if you get different readings: `for (int i = 0; i < 10; i++) { using (var mo = new ManagementObject("Win32_Processor.DeviceID='CPU0'")) { var sp = (uint)(mo["CurrentClockSpeed"]); Console.WriteLine(sp); } System.Threading.Thread.Sleep(1000); }` -- and yes, give the CPU something to do between readings. – Corak Jul 13 '18 at 20:43
  • @user9622460 I'm just testing with [WMI Code Creator](https://www.microsoft.com/en-us/download/details.aspx?id=8572). – itsme86 Jul 13 '18 at 20:50
  • @Corak, so I tried that method, and I did get a different result, but it just makes matters more confusing. When doing this, i kept task manager up to see how close it was, and like usual, it was not close. The only changes it made was going to 2400. This is very odd, and makes me think that this still isn't working. If you know processors, they vary pretty fast back and forth, and generally, they do not round to a given number over and over again. Anyone who has this working have code that I can check out? – Aaron Jul 13 '18 at 20:53
  • Figure out the 2400 value is the minimum value. – Aaron Jul 13 '18 at 21:25
  • So has anyone found an answer to my problem? I have found out the issue with the adjusting clock value, but I am still not sure why it is not accurate? – Aaron Jul 16 '18 at 13:39

3 Answers3

1

On the WMI object the MaxClockSpeed property gives you the maximum speed of the core, which should be constant. The CurrentClockSpeed property tells you the current clock speed. This may be leess than the MaxClockSpeed dues to cpu throttling.

I believe you can disable throttling at the BIOS level or via the Windows power management control panel applet, so it's possible that *CurrentClockSpeed** will always be the same as MaxClockSpeed.

Sean
  • 60,939
  • 11
  • 97
  • 136
  • But the thing that I am looking for IS the current clock speed. But it returns a value that is untrue, being my max clock speed. – Aaron Jul 16 '18 at 16:13
  • How do you know the speed returned is incorrect? How have you determines your current clock speed? – Sean Jul 16 '18 at 16:14
  • Say I use something like task manager. I can see that my cpu is not running at max (3.40 GHz). It might be running at 2.24 GHz. With no sudden spikes in GHz, the returned value is always either 3400, or 2400 (being max/min). – Aaron Jul 16 '18 at 16:19
  • @user9622460 My experience with WMI is that it's often useless for this kind of stuff. I've tried using it for CPU speed (among other things), saw the same things you are seeing now, and gave up. I was also doing this from C++ so I could drop all the way down to inline assembly if I needed to. But all the instructions that are needed are kernel-mode instructions. And reading around it does seem like you need to write a kernel-mode driver to do these things accurately. – Mysticial Jul 16 '18 at 16:25
  • How might I go along doing something like that? – Aaron Jul 16 '18 at 16:29
  • Kernel or Ring 0 is a little much... ever heard of CPUID? What about SMBIos? An no you don't need a privileged operation, you can do it rather easily using a delegate .. see https://github.com/juliusfriedman/net7mma/blob/master/Concepts/Classes/Intrinsics.cs – Jay Jul 16 '18 at 16:30
  • @Jay I'm less faimilar with SMBios. But I am with CPUID/CPUz (albeit as a user of CPUz). That comes bundled with a properly signed kernel-mode driver. So if you can use them then use it. But underneath, CPUID/CPUz still drop all the way down to the kernel/ring0. Which is why it requires admin to run. – Mysticial Jul 16 '18 at 16:34
  • I'm still quite new to coding and all, so I am unsure as to how I would implement any of that. – Aaron Jul 16 '18 at 16:37
  • Ring 0 kernel modules are not required for cpuid, see the link above... I implemented inline asm in C# and created a library which does all this for you including the cpu speed. The only caveat in calling it is ensuring you get a full time slice as profiling may start in the middle of another slice. – Jay Jul 16 '18 at 16:38
  • @Jay Without having dug through it, what instructions/API calls are you using? I'm skeptical because I've tried this many times (albeit in C++ with all Windows APIs) and I failed to get anything even remotely reliable. – Mysticial Jul 16 '18 at 16:40
  • Cpuid, you also can just estimate given a loop with An increment and the amount of time run using thread priority high – Jay Jul 16 '18 at 16:41
  • I see the link, but I am not understanding what you are saying to do with it. – Aaron Jul 16 '18 at 16:41
  • See the unit tests project, you just call the function and receive the result in Hz – Jay Jul 16 '18 at 16:42
  • @Jay If by CPUID you mean RDTSC(P), then that does not tell you the actual frequency. It only gives you a monotonic tick. It doesn't track the clock fluctuations of the clock speed. If you're just spinning a loop to see how fast it goes, that's subject to a lot of noise and will vary based on processor architecture. – Mysticial Jul 16 '18 at 16:42
  • No I meant cpuid instruction, also implemented rdtsc, and a few other intrinsic all in c# – Jay Jul 16 '18 at 16:43
  • To be honest, I am super confused on what you guys are saying to do (nothing against you're input, I am just new and don't understand!). If any of you want to give a good idea/tutorial on how I would fully implement this in my wpf program, I would super appreciate it. If not, no worries! I am just lost right now on where to look at in the links you have both provided. – Aaron Jul 16 '18 at 16:52
  • @Jay I know what the CPUID instruction is. But I'll need to see how you're doing it since I'm not aware of any CPUID feature that lets you read the clock frequency. – Mysticial Jul 16 '18 at 16:53
  • 1
    @user9622460 Since you say you are new to coding, then this probably a bit out-of-scope for you as you are finding out. IOW, learn to walk before you can run - even if "running" in this case is just pulling a GitHub repo. – Mysticial Jul 16 '18 at 16:55
  • The code for detecting the clock speed is just a math of instructions over cycles, I believe the algorithm came from Detecting CPU Speed - OSDev Wiki OSDev.org › wiki › Detecting_CPU_Speed , to implement the intrinsics I built my own class which uses a hack on delegate to execute machine code. – Jay Jul 16 '18 at 16:56
  • 1
    @Jay Oh ic. Correct me if I'm wrong, but it does look like it requires looping over a sequence of instructions with a known latency for the architecture. IOW, using a benchmark to infer the frequency as opposed to reading the crystal frequency, base clock, and frequency multiplier, or accessing the real clock counter (which requires ring0). – Mysticial Jul 16 '18 at 17:14
  • That's essentially correct, this given the known cost of compare, store, load and increment you can also estimate without the use of intrinsics, the result is fairly accurate to the Hz e.g 3100 rather than 3110 or 3123 – Jay Jul 16 '18 at 17:17
  • 1
    @Jay Got it. It's not obvious if it's usable for my usecase since it probably requires a non-negligible amount of overhead and is sensitive to noise by a hyperthread. (IOW, a 2nd thread running on the same core will slow down the thread that's trying to measure the frequency.) Useful nonetheless. Thanks! – Mysticial Jul 16 '18 at 17:21
  • Doesn't work. `CurrentClockSpeed` just returns the fixed "Base speed" value that I see on the Task Manager, not the "Speed" value that constatnly changes. – Damn Vegetables Jun 08 '20 at 16:15
0

I had the same question eight years before you did. WMI does not return the real current clock speed, and this appears to still be the case, at least through Windows 10.

For whatever reason, WMI only returns the base clock speed as the value for both maximum and current clock speed. It's not an issue of CPU support; CPU-Z is able to report the correct clock speed, as does Task Manager. It's a piece of data the OS has at its disposal, but doesn't make readily available. There's probably a way to get the exact value from the CPU using C++, but lots of devs aren't fluent in that language.

This awesome answer worked perfectly for me! I finally got this application working properly, after starting (and abandoning) it in 2010.

(P.S. This doesn't work in Windows 7; it seems the perfmon counter used didn't exist back then.)

CXL
  • 1,094
  • 2
  • 15
  • 38
-1

When running the code at an Intel CPU with access to MSRs then you may evaluate the current CPU frequency from IA32_MPERF (0xE7) TSC Frequency Clock Counter and IA32_APERF (0xE8) Actual Performance Clock Counter.

aperf_t1 = read_aperf();
mperf_t1 = read_mperf();

sleep(1);   

aperf_t2 = read_aperf();
mperf_t2 = read_mperf();

printf("CPU freq: %f [Hz]\n", ((aperf_t2-aperf_t1) / (double)(mperf_t2-mperf_t1)) * nominal_freq);
Andrew
  • 958
  • 13
  • 25