Planificación manual de CPU's con taskset

linux (el kernel, qué si no?)

Imaginemos que tenemos un sistema con 20 procesadores. Nuestro linux (si, el kernel) tiene un planificador (o scheduler) muy majo que reparte todos los procesos entre los procesadores de forma que todos se queden más o menos equiparados en cuanto a carga. Ahora supongamos que algunos procesos consumen de vez en cuando mucha CPU y no queremos que esta sobrecarga afecte a algunas CPU's (vale, es un escenario muy específico, pero os aseguro que se da Eye-wink). ¿Cómo podemos alterar esta planificación para algunos casos? pues fácil, con esta receta Smiling.

La herramienta taskset

Este programilla en Debian lo podemos encontrar en util-linux:
# aptitude install util-linux

Y es el que nos permitirá jugar con el affinity flag
En algunos sistemas esta herramienta se encuentra en el paquete schedutils.

El affinity flag

El AF es una máscara de bits que se crea para cada nuevo proceso e indica al planificador qué procesadores pueden ejecutar dicho proceso. En esta máscara cada bit representa a un procesador, siendo el procesador #0 el bit menos significativo.

Cuando un proceso se crea, por defecto su AF es 0xFFFFFFFF. Esto significa que cuando el proceso sea desalojado de un procesador, cualquier otro procesador podrá seguir con su ejecución.

Por defecto esta solución permite al planificador del kernel seleccionar cada vez cualquier CPU para cualquier proceso.

Cualquier usuario puede obtener el AF de un proceso de una forma fácil, imaginemos que el proceso tiene como PID el 12345:
$ taskset -p 12345
pid 1611's current affinity mask: 3

¡Vaya! ¡os he engañado! esto me ha dicho <3> en lugar del numerajo que os había dicho... Pues muy sencillo, en el caso del ejemplo resulta que el sistema tiene sólo 2 procesadores: esto es, los dos bits menos significativos a 1 o lo que es lo mismo, 3 en decimal. ¿Qué quiere decir esto? pues que por defecto el FA tiene a 1 todos los CPU's de nuestro sistema.

Modificar el AF

Ya sabemos como funciona por defecto el AF, ahora bien, hemos dicho que un determinado proceso no queremos que nos ocupe una determinada CPU. Lo único que debemos hacer es alterar su AF: si no queremos que pueda entrar en la CPU #0 entonces su AF debe ser 0xFFFFFFFE. Ahora supongamos que el PID de dicho proceso es 12345:
# taskset -p 0xFFFFFFFE 12345

Esta solución es válida si el proceso ya estaba en ejecución, pero si queremos lanzar uno nuevo especificando su AF:
# taskset 0xFFFFFFFE /etc/init.d/lapd start

Y si somos unos vaguetes y no queremos andar con máscaras, podemos indicar también una lista de CPU's donde puede correr nuestro proceso:
# taskset -p -c 1,2,5-8 12345

Esto hace que el proceso cuyo PID es 12345 pueda ser procesado por las CPU's #1, #2, #5, #6, #7 y #8. Si queremos lanzar un proces nuevo:
# taskset -c 0 ls

Esto hace que el comando ls sea ejecutado únicamente por la CPU #0.

Un apunte más: sólo el señor root puede establecer un FA. También lo pueden hacer usuarios con CAP_SYS_NICE activo (pero eso es harina de otro gran costal).

Más información

Básicamente:

Salud y buenos alimentos! Smiling