Saving Power with CPU Frequency Scaling

Yesterday I wrote about the climate crisis. Today, let’s start doing something about it.

Electricity, especially in the United States and China, turns out to be a pretty dirty energy source. Most of our electricity is generated using coal, which despite promises of “clean coal” to come, burns dirty. Not only does it contribute to global warming, but it also has been shown to have an adverse impact on health.

So let’s start simple: reduce the amount of electricity our computers consume. Even for an individual person, this can add up to quite a bit of energy (and money) savings in a year. When you think about multiplying this over companies, server rooms, etc., it adds up fast. This works on desktops, servers, laptops, whatever.

The easiest way to save power is with CPU frequency scaling. This is a technology that lets you adjust how fast a running CPU runs, while it’s running. When CPUs run at slower speeds, they consume less power. Most CPUs are set to their maximum speed all the time, even when the system isn’t using them. Linux has support for keeping the CPU at maximum speed unless it is idle. By turning on this feature, we can save power at virtually no cost to performance. The Linux feature to handle CPU frequency scaling is called cpufreq.

Set up modules

Let’s start by checking to see whether cpufreq support is already enabled in your kernel. These commands will need to be run as root.

# cd /sys/devices/system/cpu/cpu0
# ls -l

If you see an entry called cpufreq, you are good and can skip to the governor selection below.

If not, you’ll need to load cpufreq support into your kernel. Let’s get a list of available drivers:

# ls /lib/modules/`uname -r`/kernel/arch/*/kernel/cpu/cpufreq

Now it’s guess time. It doesn’t really hurt if you guess wrong; you’ll just get a harmless error message. One hint, though: try acpi-cpufreq last; it’s the option of last resort.

On my system, I see:

acpi-cpufreq.ko     longrun.ko      powernow-k8.ko         speedstep-smi.ko
cpufreq-nforce2.ko  p4-clockmod.ko  speedstep-centrino.ko
gx-suspmod.ko       powernow-k6.ko  speedstep-ich.ko
longhaul.ko         powernow-k7.ko  speedstep-lib.ko

For each guess, you’ll run modprobe with the driver name. I have an Athlon64, which is a K8 machine, so I run:

#modprobe powernow-k8

Note that you leave off the “.ko” bit. If you don’t get any error message, it worked.

Once you find a working module, edit /etc/modules and add the module name there (again without the “.ko”) so it will be loaded for you on boot.

Governor Selection

Next, we need to load the driver that tells the kernel what governor to use. The governor is the thing that monitors the system and adjusts the speed accordingly.

I’m going to suggest the ondemand governor. This governor keeps the system’s speed at maximum unless it is pretty sure that the system is idle. So this will be the one that will let you save power with the least performance impact.

Let’s load the module now:

# modprobe cpufreq_ondemand

You should also edit /etc/modules and add a line that says simply cpufreq_ondemand to the end of the file so that the ondemand governor loads at next boot.

Turning It On

Now, back under /sys/devices/system/cpu/cpu0, you should see a cpufreq directory. cd into it.

To turn on the ondemand governor, run this:

# echo echo ondemand > scaling_governor

That’s it, your governor is enabled. You can see what it’s doing like this:

# cat cpuinfo_min_freq
800000
# cat cpuinfo_max_freq
2200000
# cat cpuinfo_cur_freq
800000

That shows that my CPU can go as low as 800MHz, as high as 2.2GHz, and that at the present moment, it’s running at 800MHz presently.

Now, check your scaling governor settings:

# cat scaling_min_freq
800000
# cat scaling_max_freq
800000

This is showing that the system is constraining the governor to only ever operate on an 800MHz to 800MHz range. That’s not what I want; I want it to scale over the entire range of the CPU. Since my cpuinfo_max_freq was 2200000, I want to write that out to scaling_max_freq as well:

echo 2200000 > scaling_max_freq

Making This The Default

The last step is to make this happen on each boot. Open up your /etc/sysfs.conf file. If you don’t have one, you will want to run a command such as apt-get install sysfsutils (or the appropriate one for your distribution).

Add a line like this:

devices/system/cpu/cpu0/cpufreq/scaling_governor = ondemand
devices/system/cpu/cpu0/cpufreq/scaling_max_freq = 2200000

Remember to replace the 2200000 with your own cpu_max_freq value.

IMPORTANT NOTE: If you have a dual-core CPU, or more than one CPU, you’ll need to add a line for each CPU. For instance:

devices/system/cpu/cpu1/cpufreq/scaling_governor = ondemand
devices/system/cpu/cpu1/cpufreq/scaling_max_freq = 2200000

You can see what all CPU devices you have with ls /sys/devices/system/cpu.

Now, save this file, and you’ll have CPU frequency scaling saving you money, and helping the environment, every time you boot. And with the ondemand governor, chances are you’ll never notice any performance loss.

This article showed you how to save power using CPU frequency scaling on Linux. I have no idea if it’s possible to do the same on Windows, Mac, or the various BSDs, but it would be great if someone would leave comments with links to resources for doing that if so.

Updated: added scaling_max_freq info

16 thoughts on “Saving Power with CPU Frequency Scaling

  1. I tried this on a sarge system running 2.6.8-3-686

    The processor is a P4.
    This seems to need ‘p4-clockmod’

    However the only governors available seem to be the ‘performance’ one:
    # ls /lib/modules/2.6.8-3-686/kernel/drivers/cpufreq/

    cpufreq_powersave.ko cpufreq_userspace.ko
    freq_table.ko
    proc_intf.ko

    # cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors
    performance

    Do you know when the features you describe entered the 2.6 kernel?

    BTW this comparison of the modes may be of interest –
    http://www.ovro.caltech.edu/~abeard/FC3_ON_8600/governors.html

  2. Keep in mind that for home appliances, basically all wasted energy is transformed into heat. Thus in the wintertime when the outside temperature is lower than the inside temperature, and energy saved will be replaced by extra heat used by your heater. Particularly if you use electric heat, then this process gains you almost nothing.

  3. Yes, reducing the CPU power consumption will reduce heat generated. This is a good thing.

    Many data centers (server rooms) require year-round air conditioning because the servers put off so much heat. So this is a secondary power reduction from reducing CPU power draw.

    It certainly won’t make things any worse, and I’d bet that a residential furnace is more efficient at heating a residence than a CPU is.

    1. Efficiency is defined differently depending on what you’re doing.

      An efficiency of a CPU could be defined as how much energy is used in calculations (while anything that’s ‘wasted’ is heat).

      This means that if your computer is contributing to heating your home, there is no waste (at least between the outlet and the computer), and you’re basically at 100% efficiency (if you consider the heat as useful work).

      Even a high efficiency furnace, if it depends on combustion of natural gas or propane, will still allow some heat to escape out the flue in the exhaust. And an electric furnace doesn’t perform any binary calculations. :)

  4. I had to set a minimum level. After following your instructions, I found that my 3GHz CPU could run at 375MHz – And, being quite idle right now (loadavg showed 0.05), it went down.
    The system got _really_ slow. The ondemand governor might be good enough, but too much is just too much. I set a minimum speed of 1 GHz, and it feels decent.

  5. Thanks for this very nice tutorial
    Do you have any idea, how can I write a c program to adjust cpu frequency during the run time, such as which functions I can use and so on?

  6. I can’t find a driver. I’m running RHEL 4u4 AS on a dual socket quad-core Intel box. I don’t have any directories below :
    /lib/modules/`uname -r`/kernel/arch/*/kernel/

    I see nothing below /sys/devices/system/cpu/cpu#.

    I do see the on demand governors, cpufreq_powersave and cpufreq_ondemand and can modprobe them.

    What am I missing?

    Thanks.

    1. i have problem like this

      FATAL: Error inserting speedstep_centrino (/lib/modules/2.6.17-11-generic/kernel/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.ko): No such device

      i have intel core duo T2050 with speedstep

      what’s wrocng?

  7. Hey
    Got an amd 64 x2 Tl-52 Processor 2cores 1.6 GHZ!
    I followed your tutorial striaght ahead but the only thing i got working is setting ondemand as default governor!

    but whenever i try to change ‘scaling_max_freq’ in 1600000 it does nothing…
    when i do a cat it says 800000 ?!?!

    Also the Boot string that should change it on startup doesn´t work… but it works on the governor without any problem.

    so how do i get my cpu getting full speed ???
    ty for any help
    greeetz Muskatnuss

  8. I have the same problem that #9 Muskatnuss Being root I can’t write in scaling_max_freq. Even rebooting the system with the /etc/sysfs.conf modified, I get the same response, 800000 as the max freq possible. I’ll try to solve the problem.

    Anyway, thanks for this great tutorial

  9. Hi
    I have all the drivers but anyone works

    root@samba:/sys/devices/system/cpu/cpu0# ls /lib/modules/`uname -r`/kernel/arch/*/kernel/cpu/cpufreq
    acpi-cpufreq.ko gx-suspmod.ko longrun.ko powernow-k6.ko powernow-k8.ko speedstep-ich.ko speedstep-smi.ko
    cpufreq-nforce2.ko longhaul.ko p4-clockmod.ko powernow-k7.ko speedstep-centrino.ko speedstep-lib.ko
    root@samba:/sys/devices/system/cpu/cpu0# modprobe acpi-cpufreq
    FATAL: Error inserting acpi_cpufreq (/lib/modules/2.6.27-11-generic/kernel/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.ko): No such device
    root@samba:/sys/devices/system/cpu/cpu0# modprobe cpufreq-nforce2
    FATAL: Error inserting cpufreq_nforce2 (/lib/modules/2.6.27-11-generic/kernel/arch/x86/kernel/cpu/cpufreq/cpufreq-nforce2.ko): No such device
    root@samba:/sys/devices/system/cpu/cpu0# modprobe gx-suspmod
    FATAL: Error inserting gx_suspmod (/lib/modules/2.6.27-11-generic/kernel/arch/x86/kernel/cpu/cpufreq/gx-suspmod.ko): No such device
    root@samba:/sys/devices/system/cpu/cpu0# modprobe longhaul
    FATAL: Error inserting longhaul (/lib/modules/2.6.27-11-generic/kernel/arch/x86/kernel/cpu/cpufreq/longhaul.ko): No such device
    root@samba:/sys/devices/system/cpu/cpu0# modprobe longrun
    FATAL: Error inserting longrun (/lib/modules/2.6.27-11-generic/kernel/arch/x86/kernel/cpu/cpufreq/longrun.ko): No such device
    root@samba:/sys/devices/system/cpu/cpu0# modprobe powernow-k6
    FATAL: Error inserting powernow_k6 (/lib/modules/2.6.27-11-generic/kernel/arch/x86/kernel/cpu/cpufreq/powernow-k6.ko): No such device
    root@samba:/sys/devices/system/cpu/cpu0# modprobe powernow-k7
    FATAL: Error inserting powernow_k7 (/lib/modules/2.6.27-11-generic/kernel/arch/x86/kernel/cpu/cpufreq/powernow-k7.ko): No such device
    root@samba:/sys/devices/system/cpu/cpu0# modprobe powernow-k8
    FATAL: Error inserting powernow_k8 (/lib/modules/2.6.27-11-generic/kernel/arch/x86/kernel/cpu/cpufreq/powernow-k8.ko): No such device
    root@samba:/sys/devices/system/cpu/cpu0# modprobe speedstep-centrino
    FATAL: Error inserting speedstep_centrino (/lib/modules/2.6.27-11-generic/kernel/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.ko): No such device
    root@samba:/sys/devices/system/cpu/cpu0#

    I have an Intel Celeron M

    root@samba:/sys/devices/system/cpu/cpu0# cat /proc/cpuinfo
    processor : 0
    vendor_id : GenuineIntel
    cpu family : 6
    model : 15
    model name : Intel(R) Celeron(R) M CPU 520 @ 1.60GHz
    stepping : 6
    cpu MHz : 1595.962
    cache size : 1024 KB
    fdiv_bug : no
    hlt_bug : no
    f00f_bug : no
    coma_bug : no
    fpu : yes
    fpu_exception : yes
    cpuid level : 10
    wp : yes
    flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss tm pbe nx lm constant_tsc up arch_perfmon pebs bts pni monitor ds_cpl tm2 ssse3 cx16 xtpr lahf_lm
    bogomips : 3191.92
    clflush size : 64
    power management:

    Please help!!!!!!!!!!!!!!!!!!!!!!!!!!

    Thank you in advance

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.