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