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.