Le weblog entièrement nu

Roland, entièrement nu... de temps en temps.

Handmade CPU scaling

It's like this. I've got this very fine computer, only it's about four years old. Contrary to popular belief, that doesn't mean it's too slow for today's computing, so I don't feel any particular need to change it or upgrade it (I've been known to use an 8-year-old computer as my main server up till recently).

The problem is that its main processor is an Athlon XP 2200+, and that's not the "mobile" version. So there's no frequency scaling, no power-saving CPU states, and so on. And since I moved from a hot place (the French Riviera) to an even hotter place (near Montpellier), summer is likely going to cause frequent crashes as temperature rises. Oh, and my office/computer room is now right under the roof, so it does get hot rather fast.

So, something has to be done.

First solution (rather blunt): open up the computer case and point a large fan at it. It worked last summer, but it's hardly elegant, and it's noisy.

Second solution: try to emulate the CPU frequency utilities with what's available. In this case, the CPU throttling feature accessible through /proc/acpi/processor/CPU1/throttling. I had a look around, but the usual suspects (cpufrequtils, powernowd and so on) didn't seem to be able to help. Hence the following script:

#! /bin/sh

high=55
low=50
minload=1
delay=60
sensorbus=w83697hf-isa-0290
sensor=temp2
maxlevel=15

while sleep $delay ; do
  temp=$(sensors $sensorbus \
      | awk "/^$sensor:/ {print \$2}" \
      | sed s/^\+// \
      | sed s/\\..*// )
  cur=$(cat /proc/acpi/processor/CPU1/throttling \
      | awk '/^active state:/ {print $3}' \
      | sed s/T// )
  load=$(awk '{print $2}' /proc/loadavg | sed s/\\..*//)
  if [ $temp -ge $high ] && [ $cur -lt $maxlevel ] ; then
      next=$(( $cur + 1 ))
      logger "Temp $temp, load $load, throttling down from $cur to $next"
      echo $next > /proc/acpi/processor/CPU1/throttling
  elif [ $temp -le $low ] && [ $load -ge $minload ]  && [ $cur -gt 0 ] ; then
      next=$(( $cur - 1 ))
      logger "Temp $temp, load $load, throttling up from $cur to $next"
      echo $next > /proc/acpi/processor/CPU1/throttling
  fi
done

You'll notice that it unconditionnally throttles the CPU if the temperature is too high, and releases some of the power if the temperature is acceptably low and the system load seems to demand more power (no need to have the box running at full speed if it's idle).

Feel free to re-use, comment, tweak, and so on.

Update: I was pointed at athcool. It comes with big fat warnings, but it brought my CPU temperature down by 10-15 °C. Yummy.

Tags:
Creative Commons License Sauf indication contraire, le contenu de ce site est mis à disposition sous un contrat Creative Commons.