add power profile-based undervolting (fix #79)
This commit is contained in:
@@ -23,7 +23,7 @@ I will keep this list updated.
|
|||||||
I suggest you to use the excellent **[s-tui](https://github.com/amanusk/s-tui)** tool to check and monitor the CPU usage, frequency, power and temperature under load!
|
I suggest you to use the excellent **[s-tui](https://github.com/amanusk/s-tui)** tool to check and monitor the CPU usage, frequency, power and temperature under load!
|
||||||
|
|
||||||
### Undervolt
|
### Undervolt
|
||||||
The script now also supports **undervolting** the CPU by configuring voltage offsets for CPU, cache, GPU, System Agent and Analog I/O planes. The script will re-apply undervolt on resume from standby and hibernate by listening to DBus signals.
|
The script now also supports **undervolting** the CPU by configuring voltage offsets for CPU, cache, GPU, System Agent and Analog I/O planes. The script will re-apply undervolt on resume from standby and hibernate by listening to DBus signals. You can now either use the `UNDERVOLT` key in config to set global values or the `UNDERVOLT.AC` and `UNDERVOLT.BATTERY` keys to selectively set undervolt values for the two power profiles.
|
||||||
|
|
||||||
### HWP override (EXPERIMENTAL)
|
### HWP override (EXPERIMENTAL)
|
||||||
I have found that under load my CPU was not always hitting max turbo frequency, in particular when using one/two cores only. For instance, when running [prime95](https://www.mersenne.org/download/) (1 core, test #1) my CPU is limited to about 3500 MHz over the theoretical 4000 MHz maximum. The reason is the value for the HWP energy performance [hints](http://manpages.ubuntu.com/manpages/artful/man8/x86_energy_perf_policy.8.html). By default TLP sets this value to `balance_performance` on AC in order to reduce the power consumption/heat in idle. By setting this value to `performance` I was able to reach 3900 MHz in the prime95 single core test, achieving a +400 MHz boost. Since this value forces the CPU to full speed even during idle, a new experimental feature allows to automatically set HWP to performance under load and revert it to balanced when idle. This feature can be enabled (in AC mode *only*) by setting to `True` the `HWP_Mode` parameter in the config file.
|
I have found that under load my CPU was not always hitting max turbo frequency, in particular when using one/two cores only. For instance, when running [prime95](https://www.mersenne.org/download/) (1 core, test #1) my CPU is limited to about 3500 MHz over the theoretical 4000 MHz maximum. The reason is the value for the HWP energy performance [hints](http://manpages.ubuntu.com/manpages/artful/man8/x86_energy_perf_policy.8.html). By default TLP sets this value to `balance_performance` on AC in order to reduce the power consumption/heat in idle. By setting this value to `performance` I was able to reach 3900 MHz in the prime95 single core test, achieving a +400 MHz boost. Since this value forces the CPU to full speed even during idle, a new experimental feature allows to automatically set HWP to performance under load and revert it to balanced when idle. This feature can be enabled (in AC mode *only*) by setting to `True` the `HWP_Mode` parameter in the config file.
|
||||||
|
|||||||
@@ -40,7 +40,19 @@ HWP_Mode: False
|
|||||||
# Set cTDP to normal=0, down=1 or up=2 (EXPERIMENTAL)
|
# Set cTDP to normal=0, down=1 or up=2 (EXPERIMENTAL)
|
||||||
cTDP: 0
|
cTDP: 0
|
||||||
|
|
||||||
[UNDERVOLT]
|
[UNDERVOLT.BATTERY]
|
||||||
|
# CPU core voltage offset (mV)
|
||||||
|
CORE: 0
|
||||||
|
# Integrated GPU voltage offset (mV)
|
||||||
|
GPU: 0
|
||||||
|
# CPU cache voltage offset (mV)
|
||||||
|
CACHE: 0
|
||||||
|
# System Agent voltage offset (mV)
|
||||||
|
UNCORE: 0
|
||||||
|
# Analog I/O voltage offset (mV)
|
||||||
|
ANALOGIO: 0
|
||||||
|
|
||||||
|
[UNDERVOLT.AC]
|
||||||
# CPU core voltage offset (mV)
|
# CPU core voltage offset (mV)
|
||||||
CORE: 0
|
CORE: 0
|
||||||
# Integrated GPU voltage offset (mV)
|
# Integrated GPU voltage offset (mV)
|
||||||
|
|||||||
@@ -23,11 +23,9 @@ from threading import Event, Thread
|
|||||||
from time import time
|
from time import time
|
||||||
|
|
||||||
DEFAULT_SYSFS_POWER_PATH = '/sys/class/power_supply/AC*/online'
|
DEFAULT_SYSFS_POWER_PATH = '/sys/class/power_supply/AC*/online'
|
||||||
|
|
||||||
VOLTAGE_PLANES = {'CORE': 0, 'GPU': 1, 'CACHE': 2, 'UNCORE': 3, 'ANALOGIO': 4}
|
VOLTAGE_PLANES = {'CORE': 0, 'GPU': 1, 'CACHE': 2, 'UNCORE': 3, 'ANALOGIO': 4}
|
||||||
|
|
||||||
TRIP_TEMP_RANGE = [40, 97]
|
TRIP_TEMP_RANGE = [40, 97]
|
||||||
|
UNDERVOLT_KEYS = ('UNDERVOLT', 'UNDERVOLT.AC', 'UNDERVOLT.BATTERY')
|
||||||
power = {'source': None, 'method': 'polling'}
|
power = {'source': None, 'method': 'polling'}
|
||||||
|
|
||||||
platform_info_bits = {
|
platform_info_bits = {
|
||||||
@@ -245,7 +243,9 @@ def calc_undervolt_mv(msr_value):
|
|||||||
|
|
||||||
def undervolt(config):
|
def undervolt(config):
|
||||||
for plane in VOLTAGE_PLANES:
|
for plane in VOLTAGE_PLANES:
|
||||||
write_offset_mv = config.getfloat('UNDERVOLT', plane, fallback=0.0)
|
write_offset_mv = config.getfloat(
|
||||||
|
'UNDERVOLT.{:s}'.format(power['source']), plane, fallback=config.getfloat('UNDERVOLT', plane, fallback=0.0)
|
||||||
|
)
|
||||||
write_value = calc_undervolt_msr(plane, write_offset_mv)
|
write_value = calc_undervolt_msr(plane, write_offset_mv)
|
||||||
writemsr(0x150, write_value)
|
writemsr(0x150, write_value)
|
||||||
if args.debug:
|
if args.debug:
|
||||||
@@ -286,17 +286,30 @@ def load_config():
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# fix any invalid value (ie. < 0) in the undervolt settings
|
||||||
|
for key in UNDERVOLT_KEYS:
|
||||||
for plane in VOLTAGE_PLANES:
|
for plane in VOLTAGE_PLANES:
|
||||||
value = config.getfloat('UNDERVOLT', plane)
|
if key in config:
|
||||||
|
value = config.getfloat(key, plane)
|
||||||
valid_value = min(0, value)
|
valid_value = min(0, value)
|
||||||
if value != valid_value:
|
if value != valid_value:
|
||||||
config.set('UNDERVOLT', plane, str(valid_value))
|
config.set(key, plane, str(valid_value))
|
||||||
print(
|
print(
|
||||||
'[!] Overriding invalid "UNDERVOLT" value in "{:s}" voltage plane: {:.0f} -> {:.0f}'.format(
|
'[!] Overriding invalid "{:s}" value in "{:s}" voltage plane: {:.0f} -> {:.0f}'.format(
|
||||||
plane, value, valid_value
|
key, plane, value, valid_value
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# handle the case where only one of UNDERVOLT.AC, UNDERVOLT.BATTERY keys exists
|
||||||
|
# by forcing the other key to all zeros (ie. no undervolt)
|
||||||
|
if any(key in config for key in UNDERVOLT_KEYS[1:]):
|
||||||
|
for key in UNDERVOLT_KEYS[1:]:
|
||||||
|
if key not in config:
|
||||||
|
config.add_section(key)
|
||||||
|
for plane in VOLTAGE_PLANES:
|
||||||
|
value = config.getfloat(key, plane, fallback=0.0)
|
||||||
|
config.set(key, plane, str(value))
|
||||||
|
|
||||||
return config
|
return config
|
||||||
|
|
||||||
|
|
||||||
@@ -595,7 +608,7 @@ def main():
|
|||||||
bus = dbus.SystemBus()
|
bus = dbus.SystemBus()
|
||||||
|
|
||||||
# add dbus receiver only if undervolt is enabled in config
|
# add dbus receiver only if undervolt is enabled in config
|
||||||
if any(config.getfloat('UNDERVOLT', plane) != 0 for plane in VOLTAGE_PLANES):
|
if any(config.getfloat(key, plane, fallback=0) != 0 for plane in VOLTAGE_PLANES for key in UNDERVOLT_KEYS):
|
||||||
bus.add_signal_receiver(
|
bus.add_signal_receiver(
|
||||||
handle_sleep_callback, 'PrepareForSleep', 'org.freedesktop.login1.Manager', 'org.freedesktop.login1'
|
handle_sleep_callback, 'PrepareForSleep', 'org.freedesktop.login1.Manager', 'org.freedesktop.login1'
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user