5

I would like to do some microbenchmarks, and try to do them right. Unfortunately dynamic frequency scaling makes benchmarking highly unreliable.

Is there a way to programmatically (C++, Windows) find out if dynamic frequency scaling is enabled? If, can this be disabled in a program?

Ive tried to just use a warmup phase that uses 100% CPU for a second before the actual benchmark takes place, but this turned out to be not reliable either.

UPDATE: Even when I disable SpeedStep in the BIOS, cpu-z shows that the frequency changes between 1995 and 2826 GHz

martinus
  • 17,736
  • 15
  • 72
  • 92

3 Answers3

9

In general, you need to do the following steps:

  • Call CallNtPowerInformation() and pass SystemPowerCapabilities to InformationLevel parameter, set lpInputBuffer and nInputBufferSize to NULL, then set lpOutputBuffer to SYSTEM_POWER_CAPABILITIES structure, and set nOutputBufferSize to the size of the structure. After this first call, SYSTEM_POWER_CAPABILITIES structure containing the current system power capabilities. To check whether the system supports processor throttling, read the value of ProcessorThrottle.

  • There are other two members we are interested in, they are, ProcessorMinThrottle and ProcessorMaxThrottle; they represents the minimum and maximum level of system processor throttling supported, expressed as a percentage. If both members has already values 100%, this means CPU throttling is currently disabled, so you don't need to reconfigure it.

  • To disable CPU throttling, you need to set ProcessorMinThrottle and ProcessorMaxThrottle to 100%. To do this, call CallNtPowerInformation() again and pass SystemPowerCapabilities to InformationLevel parameter; but now, set lpInputBuffer to the SYSTEM_POWER_CAPABILITIES structure in which the two members has been set to 100%. I'm sure you know what to do next.

In non-programmatic way, you can also get/set Windows Power Options using the Windows built-in command-line tools, that is, PowerCfg.

Further Reading

Vantomex
  • 2,247
  • 5
  • 20
  • 22
  • Thanks for this. This was useful. One question, though. Is this permanent or just for the time the application runs? – Glenn1234 Feb 27 '13 at 07:41
  • 2
    From the MSDN: SystemPowerCapabilities 4 - The lpInBuffer parameter must be NULL, otherwise, the function returns ERROR_INVALID_PARAMETER. Did someone actually verify this works? – kalmiya Dec 18 '13 at 10:11
  • `ProcessorThrottle` is constantly `FALSE` for me and the throttle percentages are constantly 0, although I'm certain that my Laptop does frequency scaling. `CallNtPowerInformation` returned `ERROR_SUCCESS`. I'm not sure what is going on. – Sebastian Graf Aug 24 '18 at 08:17
2

So far, none of the above CallNtPowerInformation options worked for me. The relevant ProcessorThrottle field of SYSTEM_POWER_CAPABILITIES was FALSE and changing some SYSTEM_POWER_POLICYs didn't work.

However, https://www.geeks3d.com/20170213/how-to-disable-intel-turbo-boost-technology-on-a-notebook/#_24 outlines a way to make an option available in the power management settings.

With ProcMon, I was able to trace it back to the following registry manipulations:

  1. Read the ActivePowerScheme SZ value under HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Power\User\PowerSchemes to get the active power plan
  2. Set the ACSettingIndex and/or DCSettingIndex DWORD under Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Power\User\PowerSchemes\<above active power plan GUID>\54533251-82be-4824-96c1-47b60b740d00\be337238-0d82-4146-a960-4f3749d470c7 to 0 (Disabled, or whatever you choose) from 2 (High)

Unfortunately, the relevant keys are owned by the system, which either means you have to prompt the user (which has to have admin access) to change the permissions of the key or you have to use powercfg to manipulate the setting. The latter is preferrable and actually seems to work, even without admin access (courtesy of https://learn.microsoft.com/en-us/windows-server/administration/performance-tuning/hardware/power/power-performance-tuning#processor-performance-boost-mode):

powercfg -setacvalueindex scheme_current sub_processor PERFBOOSTMODE 0
powercfg -setdcvalueindex scheme_current sub_processor PERFBOOSTMODE 0
powercfg -setactive scheme_current
Sebastian Graf
  • 3,602
  • 3
  • 27
  • 38
  • 1
    Are you on a Skylake or later CPU? Skylake introduced the ability for the OS to fully hand off control of P-states (frequency scaling) to the hardware. In older CPUs, that was only done for Turbo frequencies (above the "rated" frequency, where HW needs to be able to back off on its own). But in Skylake, Turbo isn't as "special", and I think the way the OS would disable it is different in hardware-P-state mode. Anyway, this might explain why other answers no longer work. (I don't use Windows, so IDK the details.) – Peter Cordes Aug 26 '18 at 00:10
  • Thanks! That might indeed explain why it "doesn't work" anymore. – Sebastian Graf Aug 26 '18 at 17:44
0

In Windows XP and later CPU speed is managed by power policy. Doesn't it turn off the scaling if you set "Max performance" mode in Windows power management dialog?

There're also some third party tools - SpeedSwitchXP for example.

Programmatically this could be done, I suppose, using CallNtPowerInformation function.

VladV
  • 10,093
  • 3
  • 32
  • 48