Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

uncore: Allow to configure frequency limits using percent #611

Merged
merged 1 commit into from
Jul 22, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 57 additions & 12 deletions tuned/plugins/plugin_uncore.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,25 @@ class UncorePlugin(hotplug.Plugin):
`uncore`::

`max_freq_khz, min_freq_khz`:::
Limit the maximum and minumum uncore frequency.
Limit the maximum and minimum uncore frequency.

Those options are Intel specific and correspond directly to `sysfs` files
exposed by Intel uncore frequency driver.
exposed by Intel uncore frequency driver. Values can be specified as kHz
or as percent of configurable range.
====
----
[uncore]
[uncore10]
type=uncore
devices=uncore10
max_freq_khz=4000000

[uncore_all]
type=uncore
max_freq_khz=90%
----
Using this options *TuneD* will limit maximum frequency of all uncore units
on the Intel system to 4 GHz.
on the Intel system to 90% of the allowable range. Except uncore10 which
maximum frequency limit will be set to 4 GHz.
====
"""

Expand Down Expand Up @@ -75,28 +83,35 @@ def _set(self, dev_dir, file, value):
return value
return None

def _get_all(self, device):
try:
initial_max_freq_khz = self._get(device, "initial_max_freq_khz")
initial_min_freq_khz = self._get(device, "initial_min_freq_khz")
max_freq_khz = self._get(device, "max_freq_khz")
min_freq_khz = self._get(device, "min_freq_khz")
except (OSError, IOError):
log.error("fail to read uncore frequency values")
return None
return (initial_max_freq_khz, initial_min_freq_khz, max_freq_khz, min_freq_khz)

@classmethod
def _get_config_options(cls):
return {
"max_freq_khz": None,
"min_freq_khz": None,
}

def _validate_value(self, device, min_or_max, value):
def _validate_khz_value(self, device, min_or_max, value):
try:
freq_khz = int(value)
except ValueError:
log.error("value '%s' is not integer" % value)
return None

try:
initial_max_freq_khz = self._get(device, "initial_max_freq_khz")
initial_min_freq_khz = self._get(device, "initial_min_freq_khz")
max_freq_khz = self._get(device, "max_freq_khz")
min_freq_khz = self._get(device, "min_freq_khz")
except (OSError, IOError):
log.error("fail to read inital uncore frequency values")
values = self._get_all(device)
if values is None:
return None
(initial_max_freq_khz, initial_min_freq_khz, max_freq_khz, min_freq_khz) = values

if min_or_max == IS_MAX:
if freq_khz < min_freq_khz:
Expand All @@ -121,6 +136,36 @@ def _validate_value(self, device, min_or_max, value):

return freq_khz

def _validate_percent_value(self, value):
try:
pct = int(value)
except ValueError:
log.error("value '%s' is not integer" % value)
return None

if pct < 0 or pct > 100:
log.error("percent value '%s' is not within [0..100] range" % value)
return None

return pct

def _validate_value(self, device, min_or_max, value):
if isinstance(value, str) and value[-1] == "%":
pct = self._validate_percent_value(value.rstrip("%"))
if pct is None:
return None

values = self._get_all(device)
if values is None:
return None
(initial_max_freq_khz, initial_min_freq_khz, _, _) = values

khz = initial_min_freq_khz + int(pct * (initial_max_freq_khz - initial_min_freq_khz) / 100)
else:
khz = value

return self._validate_khz_value(device, min_or_max, khz)

@command_set("max_freq_khz", per_device = True)
def _set_max_freq_khz(self, value, device, sim, remove):
max_freq_khz = self._validate_value(device, IS_MAX, value)
Expand Down
Loading