1

I need to set a fixed frequency on my CPUs for a research project.

I'm using Ubuntu 20.04.5 LTS (GNU/Linux 5.4.0-155-generic x86_64) and an intel CPU Xeon W-2155 3.3GHz.

I'm trying to use the cpufrequtils package to do that. Governor is powersave.

$ cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
powersave
powersave
powersave
powersave
powersave
powersave
powersave
powersave
powersave
powersave

As far as I know, I can set the frequency with the -d (min. freq.) and -u (max. freq.) cpufreq-set arguments. I run:

sudo cpufreq-set -c 0 -d 1.8GHz -u 1.8GHz

To set CPU 0 frequency to 1.8GHz.

Then if I run cpufreq-info, I see that the limits are set, but they are not taking effect.

analyzing CPU 0:
  driver: intel_pstate
  CPUs which run at the same hardware frequency: 0
  CPUs which need to have their frequency coordinated by software: 0
  maximum transition latency: 4294.55 ms.
  hardware limits: 1.20 GHz - 4.50 GHz
  available cpufreq governors: performance, powersave
  current policy: frequency should be within 1.80 GHz and 1.80 GHz.
                  The governor "powersave" may decide which speed to use
                  within this range.
  current CPU frequency is 1.31 GHz.

Why the current CPU frequency is out of the governor limits? I used a similar approach in another server/cpu (i7-7700K 4.2GHz, though) and got the desired frequency fixed.

(Similar question here, but it was not solved.)

exepe
  • 71

1 Answers1

1

For the generations of Intel processors of the question, there is only one CPU clock generator for all CPUs, driven by a Phase Locked Loop, PLL. The PLL takes a finite amount of time to ramp up or down to whatever CPU frequency it decides to generate. CPUs in deep idle states relinquish their vote as to desired CPU frequency. Other CPUs requesting a higher CPU frequency can override the max frequency of another.

To always generate 1.8GHz CPU frequency, the min and max frequency for all CPUs needs to be set to that value AND deep idle states need to be disabled for at least one CPU (at the cost of power) such that there always at least one CPU submitting a vote request to the PLL for pstate 18 (at 100MHz per pstate). Example using CPU 5 as my test CPU:

doug@s19:~$ echo 1800000 | sudo tee /sys/devices/system/cpu/cpufreq/policy*/scaling_max_freq
1800000
doug@s19:~$ grep . /sys/devices/system/cpu/cpufreq/policy*/scaling_max_freq
/sys/devices/system/cpu/cpufreq/policy0/scaling_max_freq:1800000
/sys/devices/system/cpu/cpufreq/policy10/scaling_max_freq:1800000
/sys/devices/system/cpu/cpufreq/policy11/scaling_max_freq:1800000
/sys/devices/system/cpu/cpufreq/policy1/scaling_max_freq:1800000
/sys/devices/system/cpu/cpufreq/policy2/scaling_max_freq:1800000
/sys/devices/system/cpu/cpufreq/policy3/scaling_max_freq:1800000
/sys/devices/system/cpu/cpufreq/policy4/scaling_max_freq:1800000
/sys/devices/system/cpu/cpufreq/policy5/scaling_max_freq:1800000
/sys/devices/system/cpu/cpufreq/policy6/scaling_max_freq:1800000
/sys/devices/system/cpu/cpufreq/policy7/scaling_max_freq:1800000
/sys/devices/system/cpu/cpufreq/policy8/scaling_max_freq:1800000
/sys/devices/system/cpu/cpufreq/policy9/scaling_max_freq:1800000
doug@s19:~$ echo 1800000 | sudo tee /sys/devices/system/cpu/cpufreq/policy*/scaling_min_freq
1800000
doug@s19:~$ grep . /sys/devices/system/cpu/cpufreq/policy*/scaling_min_freq
/sys/devices/system/cpu/cpufreq/policy0/scaling_min_freq:1800000
/sys/devices/system/cpu/cpufreq/policy10/scaling_min_freq:1800000
/sys/devices/system/cpu/cpufreq/policy11/scaling_min_freq:1800000
/sys/devices/system/cpu/cpufreq/policy1/scaling_min_freq:1800000
/sys/devices/system/cpu/cpufreq/policy2/scaling_min_freq:1800000
/sys/devices/system/cpu/cpufreq/policy3/scaling_min_freq:1800000
/sys/devices/system/cpu/cpufreq/policy4/scaling_min_freq:1800000
/sys/devices/system/cpu/cpufreq/policy5/scaling_min_freq:1800000
/sys/devices/system/cpu/cpufreq/policy6/scaling_min_freq:1800000
/sys/devices/system/cpu/cpufreq/policy7/scaling_min_freq:1800000
/sys/devices/system/cpu/cpufreq/policy8/scaling_min_freq:1800000
/sys/devices/system/cpu/cpufreq/policy9/scaling_min_freq:1800000
doug@s19:~/idle$ grep . /sys/devices/system/cpu/cpu5/cpuidle/state*/name
/sys/devices/system/cpu/cpu5/cpuidle/state0/name:POLL
/sys/devices/system/cpu/cpu5/cpuidle/state1/name:C1
/sys/devices/system/cpu/cpu5/cpuidle/state2/name:C2
/sys/devices/system/cpu/cpu5/cpuidle/state3/name:C3
doug@s19:~/idle$ grep . /sys/devices/system/cpu/cpu5/cpuidle/state*/disable
/sys/devices/system/cpu/cpu5/cpuidle/state0/disable:0
/sys/devices/system/cpu/cpu5/cpuidle/state1/disable:0
/sys/devices/system/cpu/cpu5/cpuidle/state2/disable:0
/sys/devices/system/cpu/cpu5/cpuidle/state3/disable:0
doug@s19:~/idle$ echo 1 | sudo tee /sys/devices/system/cpu/cpu5/cpuidle/state1/disable
1
doug@s19:~/idle$ echo 1 | sudo tee /sys/devices/system/cpu/cpu5/cpuidle/state2/disable
1
doug@s19:~/idle$ echo 1 | sudo tee /sys/devices/system/cpu/cpu5/cpuidle/state3/disable
1
doug@s19:~/idle$ grep . /sys/devices/system/cpu/cpu5/cpuidle/state*/disable
/sys/devices/system/cpu/cpu5/cpuidle/state0/disable:0
/sys/devices/system/cpu/cpu5/cpuidle/state1/disable:1
/sys/devices/system/cpu/cpu5/cpuidle/state2/disable:1
/sys/devices/system/cpu/cpu5/cpuidle/state3/disable:1

Note: Your number of idle states might be different. Just disable all except state 0. Now observe the CPU frequencies:

doug@s19:~/idle$ grep . /sys/devices/system/cpu/cpufreq/policy*/scaling_cur_freq
/sys/devices/system/cpu/cpufreq/policy0/scaling_cur_freq:1801307
/sys/devices/system/cpu/cpufreq/policy10/scaling_cur_freq:1800484
/sys/devices/system/cpu/cpufreq/policy11/scaling_cur_freq:1801825
/sys/devices/system/cpu/cpufreq/policy1/scaling_cur_freq:1800432
/sys/devices/system/cpu/cpufreq/policy2/scaling_cur_freq:1801306
/sys/devices/system/cpu/cpufreq/policy3/scaling_cur_freq:1803848
/sys/devices/system/cpu/cpufreq/policy4/scaling_cur_freq:1800934
/sys/devices/system/cpu/cpufreq/policy5/scaling_cur_freq:1800000
/sys/devices/system/cpu/cpufreq/policy6/scaling_cur_freq:1801484
/sys/devices/system/cpu/cpufreq/policy7/scaling_cur_freq:1799961
/sys/devices/system/cpu/cpufreq/policy8/scaling_cur_freq:1800669
/sys/devices/system/cpu/cpufreq/policy9/scaling_cur_freq:1799992

Use turbostat (linux_tools_common package, I think) to monitor:

$ sudo turbostat --Summary --quiet --show Busy%,Bzy_MHz,IRQ,PkgWatt,PkgTmp,RAMWatt,GFXWatt,CorWatt --interval 10
Busy%   Bzy_MHz IRQ     PkgTmp  PkgWatt CorWatt GFXWatt RAMWatt
8.32    1800    2910    38      3.27    2.62    0.00    1.33
8.32    1800    2757    38      3.19    2.53    0.00    1.33
8.32    1800    2750    39      2.99    2.33    0.00    1.33

Note: This answer was written using kernel 5.4.0-156-generic, to be similar to what the question was using. Readers using more recent kernels will get different results for actual frequencies because things have changed and idle CPUs are no longer woken just to read the frequency. A default is returned in that case. Example using kernel 6.5:

doug@s19:~$ grep . /sys/devices/system/cpu/cpufreq/policy*/scaling_cur_freq
/sys/devices/system/cpu/cpufreq/policy0/scaling_cur_freq:4100000
/sys/devices/system/cpu/cpufreq/policy10/scaling_cur_freq:1800006
/sys/devices/system/cpu/cpufreq/policy11/scaling_cur_freq:4100000
/sys/devices/system/cpu/cpufreq/policy1/scaling_cur_freq:1799751
/sys/devices/system/cpu/cpufreq/policy2/scaling_cur_freq:4100000
/sys/devices/system/cpu/cpufreq/policy3/scaling_cur_freq:4100000
/sys/devices/system/cpu/cpufreq/policy4/scaling_cur_freq:1799571
/sys/devices/system/cpu/cpufreq/policy5/scaling_cur_freq:1799995
/sys/devices/system/cpu/cpufreq/policy6/scaling_cur_freq:4100000
/sys/devices/system/cpu/cpufreq/policy7/scaling_cur_freq:4100000
/sys/devices/system/cpu/cpufreq/policy8/scaling_cur_freq:1800304
/sys/devices/system/cpu/cpufreq/policy9/scaling_cur_freq:1800337

where the 4.1 GHz number is a default for an idle CPU. Note that that is above the 1.8GHz max we set. That will change to the current min in future.

Doug Smythies
  • 16,146