Skip to content

Conversation

spandruvada
Copy link

The Efficiency Latency Control (ELC) feature improves performance per watt. With this feature hardware power management algorithms optimize trade-off between latency and power consumption.

Add additional configuration for uncore plugin to include attributes to configure ELC.

Refer to Intel White Paper
https://www.intel.com/content/www/us/en/content-details/826934/intel-xeon-6-processors-performance-and-power-profiles-default-latency-optimized-mode-and-other-options.html?DocID=826934

Linux kernel documentation:
https://docs.kernel.org/admin-guide/pm/intel_uncore_frequency_scaling.html

Example configuration:

If the average CPU utilization is below 10% (elc_low_threshold_percent attribute below), uncore floor frequency of 1400MHz will be used (elc_floor_freq_khz attribute below) instead of hardware calculated minimum.

[uncore_all]
type=uncore
elc_floor_freq_khz=1400000
elc_high_threshold_enable=1
elc_high_threshold_percent=95
elc_low_threshold_percent=10

The Efficiency Latency Control (ELC) feature improves performance per
watt. With this feature hardware power management algorithms optimize
trade-off between latency and power consumption.

Add additional configuration for uncore plugin to include attributes
to configure ELC.

Refer to Intel White Paper
https://www.intel.com/content/www/us/en/content-details/826934/intel-xeon-6-processors-performance-and-power-profiles-default-latency-optimized-mode-and-other-options.html?DocID=826934

Linux kernel documentation:
https://docs.kernel.org/admin-guide/pm/intel_uncore_frequency_scaling.html

Example configuration:

If the average CPU utilization is below 10% (elc_low_threshold_percent
attribute below), uncore floor frequency of 1400MHz will be used
(elc_floor_freq_khz attribute below) instead of hardware calculated
minimum.

[uncore_all]
type=uncore
elc_floor_freq_khz=1400000
elc_high_threshold_enable=1
elc_high_threshold_percent=95
elc_low_threshold_percent=10
@jmencak
Copy link
Contributor

jmencak commented Apr 18, 2025

Thank you for the PR, @spandruvada , much appreciated! Let me try to get my hands on a more recent Intel system that supports this so that I can test this.

@jmencak
Copy link
Contributor

jmencak commented May 5, 2025

Got my hands on a hardware to test this on today. Hopefully I get to keep it for at least 2 weeks. However, I'm seeing:

2025-05-05 16:08:36,273 ERROR    tuned.units.manager: BUG: Unhandled exception in start_tuning: UncorePlugin._get_elc_floor_freq_khz() got multiple values for argument 'ignore_missing'
2025-05-05 16:08:36,273 ERROR    tuned.units.manager: Traceback (most recent call last):
  File "/usr/lib/python3.12/site-packages/tuned/units/manager.py", line 121, in _try_call
    return f(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/tuned/plugins/instance/instance.py", line 85, in apply_tuning
    self._plugin.instance_apply_tuning(self)
  File "/usr/lib/python3.12/site-packages/tuned/plugins/base.py", line 274, in instance_apply_tuning
    self._instance_apply_static(instance)
  File "/usr/lib/python3.12/site-packages/tuned/plugins/base.py", line 335, in _instance_apply_static
    self._execute_all_device_commands(instance, instance.assigned_devices)
  File "/usr/lib/python3.12/site-packages/tuned/plugins/base.py", line 461, in _execute_all_device_commands
    self._execute_device_command(instance, command, device, new_value)
  File "/usr/lib/python3.12/site-packages/tuned/plugins/base.py", line 524, in _execute_device_command
    new_value = self._check_and_save_value(instance, command, device, new_value)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/tuned/plugins/base.py", line 514, in _check_and_save_value
    current_value = self._get_current_value(instance, command, device)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/site-packages/tuned/plugins/base.py", line 509, in _get_current_value
    return command["get"](device, instance, ignore_missing=ignore_missing)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: UncorePlugin._get_elc_floor_freq_khz() got multiple values for argument 'ignore_missing'

2025-05-05 16:08:36,273 INFO     tuned.daemon.daemon: static tuning from profile 'uncore' applied

I'm testing this with the latest TuneD commit 9392599b, so things might have changed since you tested this, @spandruvada .

Edit: Getting this both on RHEL10 snapshot with python 3.12 and also CentOS Stream 9 with python 3.9.

@yarda
Copy link
Contributor

yarda commented May 6, 2025

It seems it was extension of the internal API earlier which broke it, it needs changes to the @command_get and @command_set, it now requires the instance parameter, e.g:

@command_get("elc_low_threshold_percent")
def _get_elc_low_threshold_percent(self, device, ignore_missing=False):
...
@command_set("elc_high_threshold_enable", per_device = True)
def _set_elc_high_threshold_enable(self, value, device, sim, remove):

needs to be now:

@command_get("elc_low_threshold_percent")
def _get_elc_low_threshold_percent(self, device, instance, ignore_missing=False):
...
@command_set("elc_high_threshold_enable", per_device = True)
def _set_elc_high_threshold_enable(self, value, device, instance, sim, remove):

This has to be changed in the all get/set.

@jmencak
Copy link
Contributor

jmencak commented May 6, 2025

It seems it was extension of the internal API earlier which broke it, it needs changes to the @command_get and @command_set, it now requires the instance parameter, e.g:

@command_get("elc_low_threshold_percent")
def _get_elc_low_threshold_percent(self, device, ignore_missing=False):
...
@command_set("elc_high_threshold_enable", per_device = True)
def _set_elc_high_threshold_enable(self, value, device, sim, remove):

needs to be now:

@command_get("elc_low_threshold_percent")
def _get_elc_low_threshold_percent(self, device, instance, ignore_missing=False):
...
@command_set("elc_high_threshold_enable", per_device = True)
def _set_elc_high_threshold_enable(self, value, device, instance, sim, remove):

This has to be changed in the all get/set.

Thanks, @yarda . I've tested this PR successfully on RHEL10 snapshot with Granite Rapid AP (P-cores) and CentOS Stream 9 with Sierra Forest SP (SRF-SP) (E-cores) without any issues (all 4 new knobs were set).

This is the patch I used on top of @spandruvada 's work:

diff --git a/tuned/plugins/plugin_uncore.py b/tuned/plugins/plugin_uncore.py
index ec8e05e..0b5e8a8 100644
--- a/tuned/plugins/plugin_uncore.py
+++ b/tuned/plugins/plugin_uncore.py
@@ -243,7 +243,7 @@ class UncorePlugin(hotplug.Plugin):
 		return min_freq_khz
 
 	@command_get("elc_floor_freq_khz")
-	def _get_elc_floor_freq_khz(self, device, ignore_missing=False):
+	def _get_elc_floor_freq_khz(self, device, instance, ignore_missing=False):
 		if ignore_missing and not os.path.isdir(SYSFS_DIR):
 			return None
 
@@ -257,7 +257,7 @@ class UncorePlugin(hotplug.Plugin):
 		return elc_floor_freq_khz
 
 	@command_set("elc_floor_freq_khz", per_device = True)
-	def _set_elc_floor_freq_khz(self, value, device, sim, remove):
+	def _set_elc_floor_freq_khz(self, value, device, instance, sim, remove):
 		elc_floor_freq_khz = self._validate_value(device, IS_MAX, value)
 		if elc_floor_freq_khz is None:
 			return None
@@ -269,7 +269,7 @@ class UncorePlugin(hotplug.Plugin):
 		return self._set(device, "elc_floor_freq_khz", elc_floor_freq_khz)
 
 	@command_set("elc_high_threshold_percent", per_device = True)
-	def _set_elc_high_threshold_percent(self, value, device, sim, remove):
+	def _set_elc_high_threshold_percent(self, value, device, instance, sim, remove):
 		pct = self._validate_percent_value(value.rstrip("%"))
 		if pct is None:
 			return None
@@ -281,7 +281,7 @@ class UncorePlugin(hotplug.Plugin):
 		return self._set(device, "elc_high_threshold_percent", pct)
 
 	@command_get("elc_high_threshold_percent")
-	def _get_elc_high_threshold_percent(self, device, ignore_missing=False):
+	def _get_elc_high_threshold_percent(self, device, instance, ignore_missing=False):
 		if ignore_missing and not os.path.isdir(SYSFS_DIR):
 			return None
 
@@ -295,7 +295,7 @@ class UncorePlugin(hotplug.Plugin):
 		return elc_high_threshold_percent
 
 	@command_set("elc_low_threshold_percent", per_device = True)
-	def _set_elc_low_threshold_percent(self, value, device, sim, remove):
+	def _set_elc_low_threshold_percent(self, value, device, instance, sim, remove):
 		pct = self._validate_percent_value(value.rstrip("%"))
 		if pct is None:
 			return None
@@ -307,7 +307,7 @@ class UncorePlugin(hotplug.Plugin):
 		return self._set(device, "elc_low_threshold_percent", pct)
 
 	@command_get("elc_low_threshold_percent")
-	def _get_elc_low_threshold_percent(self, device, ignore_missing=False):
+	def _get_elc_low_threshold_percent(self, device, instance, ignore_missing=False):
 		if ignore_missing and not os.path.isdir(SYSFS_DIR):
 			return None
 
@@ -321,7 +321,7 @@ class UncorePlugin(hotplug.Plugin):
 		return elc_low_threshold_percent
 
 	@command_set("elc_high_threshold_enable", per_device = True)
-	def _set_elc_high_threshold_enable(self, value, device, sim, remove):
+	def _set_elc_high_threshold_enable(self, value, device, instance, sim, remove):
 		try:
 			enable = int(value)
 		except ValueError:
@@ -339,7 +339,7 @@ class UncorePlugin(hotplug.Plugin):
 		return self._set(device, "elc_high_threshold_enable", enable)
 
 	@command_get("elc_high_threshold_enable")
-	def _get_elc_high_threshold_enable(self, device, ignore_missing=False):
+	def _get_elc_high_threshold_enable(self, device, instance, ignore_missing=False):
 		if ignore_missing and not os.path.isdir(SYSFS_DIR):
 			return None
 

Srinivas, would you be able to update your PR so that we can merge this? Thank you and our apologies for the delay.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants