CPU Frequency Scaling

From SlackWiki
Revision as of 08:42, 28 May 2009 by Ibm5 25 (talk | contribs) (Copied from /old)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

The CPU frequency scaling feature present in modern computers allows lowering and increasing the processor speed dynamically in runtime so as to save energy while having the possibility of increasing the performance and power consumption if needed. Activating CPU frequency scaling under Slackware is very easy, and requires loading a minimum of two kernel modules and running a simple command. On the one hand, you need to load a specific CPU driver that will activate the frequency scaling feature in your platform. Second, you need to choose a CPU frequency scaling governor, a module that will decide how and when to change the internal processor speed. There are governors to always run at full speed, governors to always run at low speed, governors to increase and decrease the speed based on the CPU load, etc.

It's usually desired to activate CPU frequency scaling as early as possible in the boot process, eventhough a few seconds running at full power are not that important. The easier way is, however, to enable it from the boot script /etc/rc.d/rc.local, which is executed right at the end of the boot process. Other approaches need more intrusive changes. You could load the required modules and run the commands from a modified init script of an initial RAM disk. You could do the same from a personal /etc/rc.d/rc.modules.local, or also from the already mentioned rc.local. It's up to you to decide when and where to load and activate the feature.

Loading CPU specific drivers

You first need to load one of the available CPU powersaving modules. They are included in the typical kernel module packages, and depend on the type of CPU you have. Every available module will be located in /lib/modules/$( uname -r )/kernel/arch/i386/kernel/cpu/cpufreq. For example, my CPU is a K8 processor and I use the powernow-k8 module. Inside that directory you will see a lot of module files ending with .ko. To load them, use /sbin/modprobe followed by the name before the suffix, from any location. Example:

 /sbin/modprobe powernow-k8

If you're not sure about which driver you need, proceed by trial and error. Load one module with a command like the previous one and then check the last lines of dmesg with the command dmesg | tail. If you see a successful detection, that's the module you need. If not, unload the module with /sbin/modprobe -r (example: /sbin/modprobe -r powernow-k8) and try another one. This is an example of successful output as printed by dmesg | tail:

 powernow-k8: Found 1 Mobile AMD Sempron(tm) Processor 3000+ processors (version 2.00.00)
 powernow-k8:    0 : fid 0xa (1800 MHz), vid 0x8
 powernow-k8:    1 : fid 0x8 (1600 MHz), vid 0xa
 powernow-k8:    2 : fid 0x0 (800 MHz), vid 0x13

Loading a governor module

The second step is to load a governor module. The governor most people will want to load is the one named ondemand, that will always use the lowest frequency available to fullfill the processing requirements. If your computer is idle, it will put the processor in the lowest possible speed. If you perform a very CPU-intensive task, it will increase the frequency accordingly. It's also the governor that Intel recommends to use in its laptops. All the available governor modules are located in /lib/modules/$( uname -r )/kernel/drivers/cpufreq. To use a governor, the first step is to load its corresponding module as we did previously with the CPU module. Example:

 /sbin/modprobe cpufreq_ondemand

Notice how the governor is called ondemand, yet its module is called cpufreq_ondemand.

Setting the CPU scaling governor

Loading a governor module doesn't mean it's going to be used immediately. In fact, you can load all governor modules if you want. To decide which governor will be used in a given moment, you need to set it at runtime. Each CPU can have its own governor. That is, if you have a dual core machine, you can put one of the cores in low power and other one in full power if you need it. However, the most usual case is to use the same governor in all CPUs. Each CPU has its own configuration file in the /sys filesystem. For example, the file for the first CPU is called /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor. For other CPUs, increase the digit in cpu0. You can set a governor name for all of them at the same time using a shell loop like the one in this example, that sets the ondemand governor for every CPU:

 for config_file in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do
     echo ondemand >$config_file
 done

To confirm you have successfully set the governor, see if it scales the CPU frequency. From an idle system, run grep '^cpu MHz' /proc/cpuinfo. You should see one or more lines like:

 cpu MHz         : 800.000

Then, launch a CPU intensive task from a different terminal, like yes >/dev/null and then run the previous command again. You should now see a higher number (1800.000 in my case) in at least one of the output lines. If you see the same number wait 5 seconds and try again.

Putting it all together

This can be made as sophisticated as you decide, but let's suppose you opt for the simple approach of setting everything up from rc.local. You would add the following commands if your CPU needed the module powernow-k8 and you wanted to set the ondemand governor:

 /sbin/modprobe powernow-k8
 /sbin/modprobe cpufreq_ondemand
 for config_file in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do
     echo ondemand >$config_file
 done