parseerror.com / pizza / cpufreq.html

On An Attempt to Make My Computer More Energy-Efficient By The Utilization of Dynamic CPU Frequency Scaling

I'm investigating lightening the electricity requirements for my home server. One area of interest is underclocking - that is, forcing one's CPU to run slow than its normal speed so that it uses fewer resources and generates less heat. The problem with underclocking is that it is not dynamic... most of the time my server's CPU utilization is at < 1%, but occasionally I'll run fairly CPU-heavy jobs that will crunch along at 100% for several minutes. If I underclock my CPU I'll save power most of the time, but my jobs will take longer. Luckily...

Apparently recent AMD processors support something called PowerNow! which allows us to modify the CPU frequency on-the-fly. Linux supports this, and stuff called "governors" which control the frequency-changing policy.

I'm running Linux 2.6.15 and the Gentoo distro. I've got an AMD Athlon64 3200+ CPU.

root@pizzabox# uname -a
Linux pizzabox 2.6.15-gentoo-r1 #9 PREEMPT Fri Sep 29 11:47:33 EDT 2006 i686 AMD Athlon(tm) 64 Processor 3200+ GNU/Linux
root@pizzabox# cat /proc/cpuinfo
processor       : 0
vendor_id       : AuthenticAMD
cpu family      : 15
model           : 47
model name      : AMD Athlon(tm) 64 Processor 3200+
stepping        : 2
cpu MHz         : 2002.734
cache size      : 512 KB
fdiv_bug        : no
hlt_bug         : no
f00f_bug        : no
coma_bug        : no
fpu             : yes
fpu_exception   : yes
cpuid level     : 1
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 syscall nx mmxext fxsr_opt lm 3dnowext 3dnow pni lahf_lm
bogomips        : 2007.29
root@pizzabox#
Let's recompile our kernel:
root@pizzabox# cd /usr/src/linux
root@pizzabox# make menuconfig
Power management options (ACPI, APM)  --->
	 CPU Frequency scaling  --->

[*] CPU Frequency scaling
[ ]   Enable CPUfreq debugging
<*>   CPU frequency translation statistics
[*]     CPU frequency translation statistics details
      Default CPUFreq governor (performance)  --->
---   'performance' governor
<*>   'powersave' governor
<*>   'userspace' governor for userspace frequency scaling
<*>   'ondemand' cpufreq policy governor
<*>   'conservative' cpufreq governor
---   CPUFreq processor drivers
<*>   ACPI Processor P-States driver
...
<*>   AMD Opteron/Athlon64 PowerNow!
...

root@pizzabox# mount /boot
root@pizzabox# make modules modules_install install && reboot
Our kernel compiles, installs itself and we reboot. Now, to tell Linux to run the CPU at a slower frequency by default, only speeding it up under heavy computation.
root@pizzabox# cd /sys/devices/system/cpu/cpu0/cpufreq
root@pizzabox# ls -l
total 0
-r--r--r-- 1 root root 4096 Sep 29 11:49 affected_cpus
-r-------- 1 root root 4096 Sep 29 11:49 cpuinfo_cur_freq
-r--r--r-- 1 root root 4096 Sep 29 11:49 cpuinfo_max_freq
-r--r--r-- 1 root root 4096 Sep 29 11:49 cpuinfo_min_freq
-r--r--r-- 1 root root 4096 Sep 29 11:49 scaling_available_frequencies
-r--r--r-- 1 root root 4096 Sep 29 11:49 scaling_available_governors
-r--r--r-- 1 root root 4096 Sep 29 11:49 scaling_cur_freq
-r--r--r-- 1 root root 4096 Sep 29 11:49 scaling_driver
-rw-r--r-- 1 root root 4096 Sep 29 11:49 scaling_governor
-rw-r--r-- 1 root root 4096 Sep 29 11:49 scaling_max_freq
-rw-r--r-- 1 root root 4096 Sep 29 11:49 scaling_min_freq
drwxr-xr-x 2 root root    0 Sep 29 11:49 stats
root@pizzabox# cat scaling_available_governors
conservative ondemand powersave userspace performance
root@pizzabox# cat scaling_governor
performance
root@pizzabox# grep Hz /proc/cpuinfo
cpu MHz         : 2002.734
root@pizzabox# echo "ondemand" > scaling_governor
root@pizzabox# cat scaling_governor
ondemand
root@pizzabox# cat /proc/cpuinfo |grep Hz
cpu MHz         : 1001.367
There, the "ondemand" governor is configured and we're running at 1/2 frequency. That was easy. Let's see if this thing really works. Let's create an artificial CPU-hogging process and see if we scale up to the previous freq of ~2000.
root@pizzabox# perl -le'while(1){}' &
[2] 8078
root@pizzabox# grep Hz /proc/cpuinfo
cpu MHz         : 2002.734
root@pizzabox# kill 8078
root@pizzabox#
[2]+  Terminated              perl -le'while(1){}'
root@pizzabox# grep Hz /proc/cpuinfo
cpu MHz         : 1001.367
It works! The CPU frequency runs at ~1000 by default and scales to ~2000 when the CPU is in demand. Does it make a difference? I recently got the lm_sensors package working with Linux so I can read the thermal sensors on my CPU and motherboard. Here's a day in the thermal life of my server:


This is a real rrdtool graph augmented with the labels via Photoshop.

It looks like the cpufreq does indeed make a difference. My CPU is running ~7F cooler right off the bat. We'll see if this has any effect on the motherboard temperature over a longer period of time.

I will also try reducing the core voltage (Vcore) of the CPU and see if we can get away with using a bit less power. Less energy use is the goal here. Lowering the voltage will of course use fewer watts, and if I can manage to cool my CPU down sufficiently, it may be possible to replace the active cooling (fan) with passive cooling (massive heatsink), resulting in even greater energy savings. We shall see...