Lanzar procesos en paralelo fácilmente con xargs

La paralelización de procesos entre múltiples núcleos o procesadores (SMT / CMT / SMP / HT / …) se puede realizar de dos formas. La primera es por medio de la aplicación en si al estar programada para utilizar hilos (multithreading) o librerías como TBB (Threading Building Blocks) de Intel. Otra manera es utilizar varias copias de la aplicación, pero de forma que cada copia procese un trozo de datos definido. En este caso el sistema operativo asignará procesos entre núcleos o procesadores (multitarea) de forma automática.

Con el comando xarg y su opción -P podemos utilizar la paralelización de procesos que no fueron programados para funcionar en paralelo. Veremos algunos ejemplos de uso y los beneficios en tiempos de procesamiento con el comando time.

--max-procs=max-procs
-P max-procs
    Run up to max-procs processes at a time; the default is 1. If max-procs is 0, xargs will run as many processes as possible at a time. Use the -n option with -P; otherwise chances are that only one exec will be done. 

Sin paralelización: Listamos los ficheros de un directorio y se realiza la suma md5 de cada uno de ellos.

time ls * | xargs -I ARG -P1 -n1 md5sum  ARG
real	0m3.401s
user	0m2.637s
sys	0m0.177s

Sin paralelización: Se realiza la suma md5 de cada fichero del directorio actual. Lo mismo que el anterior pero sin tubería.

time md5sum *
real	0m2.807s
user	0m2.640s
sys	0m0.170s

Paralelizar md5sum: Se crean 8 procesos md5sum que son ejecutados a la vez (paralelización).

time ls * | xargs -I ARG -P8 -n1 md5sum ARG
real	0m1.412s
user	0m2.723s
sys	0m0.230s

Ver en qué núcleo se ejecutan los procesos paralelizados.

ps -eF | grep -i md5sum
busi     12153 12151  0  3540  1404   3 16:59 pts/0    00:00:00 md5sum fichero1
busi     12154 12151  0  3540  1296   1 16:59 pts/0    00:00:00 md5sum fichero2
busi     12155 12151  0  3540  1312   1 16:59 pts/0    00:00:00 md5sum fichero3
busi     12156 12151  0  3540  1476   6 16:59 pts/0    00:00:00 md5sum fichero4
busi     12157 12151  0  3540  1360   1 16:59 pts/0    00:00:00 md5sum fichero5
busi     12158 12151  0  3540  1336   3 16:59 pts/0    00:00:00 md5sum fichero6
busi     12160 12151  0  3540  1360   2 16:59 pts/0    00:00:00 md5sum fichero7
busi     12161 12151  0  3540  1308   6 16:59 pts/0    00:00:00 md5sum fichero8

Núcleos en uso según el comando ps (Séptima columna): 1,2,3,6

¿Es posible paralelizar procesos en Bash / Shellscripts?

No, no hay métodos nativos de paralelización de procesos en bash / shellscripts. La única posibilidad que podría tener un resultado similar, es utilizar procesos en segundo plano, en conjunción con las utilidades taskset y wait. De esta manera se puede asignar determinados núcleos a cada proceso y dejar el script en espera hasta que los procesos en background terminen.

Para reservar núcleos a determinados procesos de forma exclusiva se puede utilizar la directiva “isolcpus” en el cargador de arranque GRUB, de esta manera se consigue que tras el inicio, el kernel no asigne procesos a dicho/s núcleo/s y podamos hacerlo posteriormente nosotros con la utilidad taskset.