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
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
- Power Management
- Power Management Functions
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_POLICY
s 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:
- Read the
ActivePowerScheme
SZ
value under HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Power\User\PowerSchemes
to get the active power plan
- 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://docs.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
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.