Escribe tu propio gestor de la frecuencia de la CPU

En muchos casos es interesante controlar la frecuencia de la CPU. Por ejemplo, en un portátil conviene gestionar dicho parámetro para contener el gasto energético. Por lo tanto la batería durará mucho más.

También se puede usar para hacer overclock y sacar más rendimiento al equipo.

Hay que tener en cuenta que mayor velocidad de la CPU más rendimiento, pero más consumo.

Existen programas como Jupiter (http://aleqwerty.wordpress.com/2013/04/06/ahorra-bateria-con-jupiter-ubuntu-12-10/) que te permiten controlar la frecuencia de la CPU. Pero me he encontrado casos en los que no parece funcionar correctamente.

También existen otras opciones como las que se detallan en los siguientes wikis:
https://wiki.archlinux.org/index.php/CPU_Frequency_Scaling
http://en.gentoo-wiki.com/wiki/CPU_Frequency_Scaling

Pero en ocasiones nos gustaría controlar el comportamiento de dicho escalado y definirlo a nuestro antojo.

Lo que voy a contar ahora es cómo cambiar dicha frecuencia usando nuestros propios programas. ¿Preparados? Allá vamos:

Para empezar debemos tener cargado el módulo que permite controlar la frecuencia. Los módulos disponibles se pueden encontrar usando el siguiente comando:

ls /lib/modules/$(uname -r)/kernel/drivers/cpufreq/

¿Qué módulo usar? He aquí una pequeña lista sacada de la wiki de Arch Linux:
* acpi-cpufreq CPUFreq driver which utilizes the ACPI Processor Performance States. This driver also supports Intel Enhanced SpeedStep (previously supported by the deprecated speedstep-centrino module).
* speedstep-lib CPUFreq drive for Intel speedstep enabled processors (mostly atoms and older pentiums (< 3))
* powernow-k8 CPUFreq driver for K8/K10 Athlon64/Opteron/Phenom processors. Deprecated since linux 3.7 – Use acpi_cpufreq.
* pcc-cpufreq This driver supports Processor Clocking Control interface by Hewlett-Packard and Microsoft Corporation which is useful on some Proliant servers.
* p4_clockmod CPUFreq driver for Intel Pentium 4 / Xeon / Celeron processors. When enabled it will lower CPU temperature by skipping clocks.
You probably want to use a Speedstep driver instead.

Para cargar el módulo escribimos:

	
	sudo modprobe módulo

Por ejemplo, en el caso de tener un Pentium 4:

	sudo modprobe p4_clockmod

Una vez cargado el módulo instalamos el paquete cpufrequtils:

	
	sudo apt-get install cpufrequtils

Perfecto, vamos a la carga. Escribimos en un terminal:

	
	cpufreq-info

Devolverá algo similar a lo siguiente:

cpufrequtils 008: cpufreq-info (C) Dominik Brodowski 2004-2009
Report errors and bugs to cpufreq@vger.kernel.org, please.
analyzing CPU 0:
  driver: p4-clockmod
  CPUs which run at the same hardware frequency: 0
  CPUs which need to have their frequency coordinated by software: 0
  maximum transition latency: 10.00 ms.
  hardware limits: 300 MHz - 2.40 GHz
  available frequency steps: 300 MHz, 600 MHz, 900 MHz, 1.20 GHz, 1.50 GHz, 1.80 GHz, 2.10 GHz, 2.40 GHz
  available cpufreq governors: conservative, ondemand, userspace, powersave, performance
  current policy: frequency should be within 300 MHz and 2.40 GHz.
                  The governor "userspace" may decide which speed to use
                  within this range.
  current CPU frequency is 1.20 GHz.
  cpufreq stats: 300 MHz:49,28%, 600 MHz:0,00%, 900 MHz:0,00%, 1.20 GHz:25,20%, 1.50 GHz:0,00%, 1.80 GHz:0,00%, 2.10 GHz:0,00%, 2.40 GHz:25,52%  (170)

En el caso de dar error, se puede deber a que no hemos cargado el módulo de control de la frecuencia adecuado. Habrá que volver a repetir el procesor hasta acertar.

Como se puede apreciar en la salida del comando cpufreq-info devuelve:
* La lista de las frecuencias que soporta el procesador y su uso (cpufreq stats).
* La frecuencia de funcionamiento actual (current CPU frequency is 1.20 GHz).
* El controlador actual (current policy).
* Los controladores disponibles (available cpufreq governors). Por defecto lo más seguro que esté seleccionado “performance” (rendimiento máximo y máximo consumo de energía), pero también tenemos “ondemand” (aumenta la frecuencia delñ procesador al llegar al 90% de su carga), “conservative” (aumenta la frecuencia del procesador al llegar al 70% de su carga), “powersave” (mínima frecuencia de funcionamiento para ahorrar energía) y “userspace” (lo puede cambiar el usuario a placer).

En nuestro caso, somos nosotros los que vamos a controlar la frecuencia del procesador, por lo que escribiremos:

	
	sudo cpufreq-set -g userspace

Ahora se puede cambiar la frecuencia de funcionamiento usando:

	
	sudo cpufreq-set -f 900Mhz

Por supuesto la frecuencia debe estar entre una de las frecuencias permitidas.

Con lo anterior se puede cambiar la frecuencia del reloj manualmente. Ahora toca programar algo que la controle de forma automática.

Es necesario conocer la carga de trabajo del procesador. Esta información se almacena en el archivo “/proc/stat”. Por ejemplo, si se teclea:

	
	cat /proc/stat

Se obtiene una salida similar a:

	
	cpu  31974 0 16617 126061 4251 2 137 0 0 0

¿Qué significan estos números? Mide el número de jiffies (1/100 de un segundo) que el sistema ha estado en modo usuario (user, en este caso 31974), modo usuario con prioridad baja (nice, en este caso 0), modo del sistema (system, 16617) y tarea inactiva (idle, 126061) respectivamente. Nos interesan las tres primeras columnas. Por ejemplo:

	
	echo "CPU #0: $(egrep ^cpu0 /proc/stat | awk '{printf("%3.2f", 100*($2+$3+$4)/($2+$3+$4+$5))}')%"

Devuelve en mi caso:

	
	CPU #0: 26.95%

Estos son los datos de ocupación de la CPU número 0 desde que se encendió el ordenador. Interesan los datos actuales. Para obtener la carga actual del procesador, se hacen dos lecturas seguidas y se calcula la diferencia.

Ahora toca programar. Está escrito en lenguaje C. Hay que guardar el siguiente texto en el archivo “freq-cpu.c”:

     1	#include <stdio.h>
     2	#include <stdlib.h>
     3	#include <unistd.h>
     4	
     5	// Usar cpufreq-info para conocer la lista de frecuencias soportadas
     6	
     7	void set_cpufreq(int state)
     8	{
     9		//printf("state=%d\n", state);
    10		switch(state)
    11		{
    12			case 0:
    13				system("cpufreq-set -f 300Mhz");
    14			break;
    15			case 5:
    16				system("cpufreq-set -f 1.2Ghz");
    17			break;
    18			case 6:
    19				system("cpufreq-set -f 2.4Ghz");
    20			break;
    21		}
    22	}
    23	
    24	int main(void)
    25	{
    26	    long double a[4],b[4],loadavg;
    27	    FILE *fp;
    28	    char dump[50];
    29	    int state = 10;
    30	
    31	    for(;;)
    32	    {
    33			fp = fopen("/proc/stat","r");
    34			fscanf(fp,"%*s %Lf %Lf %Lf %Lf",&a[0],&a[1],&a[2],&a[3]);
    35			fclose(fp);
    36			if(state>0)
    37				sleep(1);
    38			else
    39				usleep(300000);
    40			fp = fopen("/proc/stat","r");
    41			fscanf(fp,"%*s %Lf %Lf %Lf %Lf",&b[0],&b[1],&b[2],&b[3]);
    42			fclose(fp);
    43	
    44			loadavg = ((b[0]+b[1]+b[2]) - (a[0]+a[1]+a[2])) / ((b[0]+b[1]+b[2]+b[3]) - (a[0]+a[1]+a[2]+a[3]));
    45			loadavg*=100;
    46			//printf("The current CPU utilization is : %d\n",(int)loadavg);
    47			if(loadavg>80.0)
    48			{
    49				if(state==0)
    50				{
    51					set_cpufreq(5);
    52					state=5;
    53				}
    54				if(state<10)
    55				{
    56					state++;
    57					set_cpufreq(state);
    58				}
    59			}
    60			else if(loadavg<40.0)
    61			{
    62				if(state>0)
    63				{
    64					state--;
    65					set_cpufreq(state);
    66				}
    67			}
    68	
    69	    }
    70	
    71	    return(0);
    72	}

En cada caso habrá que modificar las líneas 13, 16 y 19 para adaptar las frecuencias en el caso de menor rendimiento, rendimiento medio y mayor. Evidentemente cuantas más frecuencias se introduzcan, más rico será el comportamiento del controlador de frecuencias.

Lo compilamos escribiendo:

	
	make freq-cpu

Una vez compilado se debe ejecutar con:

	
	sudo ./freq-cpu

Perfecto, ahora hará escalado de frecuencias de forma automática. Este controlador de frecuencias pone por defecto una frecuencia de 300 MHz, bajo rendimiento. En el caso de detectar la mínima actividad, la sube a 1.2 GHz ó a 2.4 GHz si la carga es muy alta.

Una vez que se haya ajustado al comportamiento adecuado, para ello deberemos saber programar algo en C, se puede hacer que el programa se inicie de forma automática en cada inicio. Sólo hay que modificar el archivo “rc.local”:

#!/bin/sh -e

# Se activa el escalado automático de la frecuencia de reloj
modprobe p4_clockmod    #Habrá que poner nuestro controlador
cpufreq-set -g userspace
/usr/local/bin/freq-cpu     #Ruta en la que está el ejecutable de nuestro controlador

exit 0

¿Qué modificaciones se pueden hacer?

Por ejemplo, se puede hacer que cuando se cargue un determinado programa, la frecuencia sube al máximo. Es decir, si ejecutamos nuestro juego favorito, la frecuencia deberá subir al máximo. Se pueden controlar los programas en ejecución con el comando “ps -A”.

Hay portátiles, como el EeePC 701, en los que la frecuencia del procesador no está al máximo. Hay fabricantes que hacen esto para aumentar la duración de la batería. Se puede hacer que cuando la carga del procesador esté un determinado tiempo al 100 %, se haga un overclock durante unos segundos, de forma que el rendimiento sea mayor del habitual. ¡En el EeePC se puede llegar al 142 % del rendimiento habitual!

En el caso del EeePC he llegado a tenerlo a alto rendimiento durante horas. La parte mala es que el equipo se calienta de forma inusual. Por ello que cada uno evalúe sus riesgos.

Anuncios
Esta entrada fue publicada en Hardware, Software. Guarda el enlace permanente.

2 respuestas a Escribe tu propio gestor de la frecuencia de la CPU

  1. yoo dijo:

    cuando pongo sudo modprobe modulo
    ponde
    FATAL: Module modulo not found.

  2. selairi dijo:

    Era la explicación de cómo se carga cualquier módulo. Si tienes un Pentium 4, debes hacer lo que pone a continuación:

    sudo modprobe p4_clockmod

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s