GNU/Linux >> Tutoriales Linux >  >> Linux

Haga más en la línea de comandos de Linux con GNU Parallel

¿Alguna vez has tenido la extraña sensación de que tu computadora no es tan rápida como debería? Solía ​​sentirme así, y luego encontré GNU Parallel.

GNU Parallel es una utilidad de shell para ejecutar trabajos en paralelo. Puede analizar múltiples entradas, ejecutando así su script o comando contra conjuntos de datos al mismo tiempo. Puede usar todos ¡tu CPU por fin!

Si alguna vez has usado xargs , ya sabes cómo usar Parallel. Si no es así, este artículo le enseñará, junto con muchos otros casos prácticos.

Instalación de GNU Paralelo

Es posible que GNU Parallel no venga preinstalado en su computadora con Linux o BSD. Instálelo desde su repositorio o colección de puertos. Por ejemplo, en Fedora:

$ sudo dnf install parallel

O en NetBSD:

# pkg_add parallel

Si todo lo demás falla, consulte la página de inicio del proyecto.

De serie a paralelo

Como sugiere su nombre, la fortaleza de Parallel es que ejecuta trabajos en paralelo en lugar de secuencialmente, como muchos de nosotros todavía hacemos.

Cuando ejecuta un comando contra muchos objetos, inherentemente está creando una cola. El comando puede procesar una cierta cantidad de objetos, y todos los demás objetos simplemente se quedan parados y esperan su turno. es ineficiente Con suficientes datos, siempre habrá una cola, pero en lugar de tener una sola cola, ¿por qué no tener muchas colas pequeñas?

Imagina que tienes una carpeta llena de imágenes que quieres convertir de JPEG a PNG. Hay muchas maneras de hacer esto. Existe la forma manual de abrir cada imagen en GIMP y exportarla al nuevo formato. Esa suele ser la peor manera posible. No solo requiere mucho tiempo, sino también mucha mano de obra.

Una variación bastante interesante de este tema es la solución basada en shell:

$ convert 001.jpeg 001.png
$ convert 002.jpeg 002.png
$ convert 003.jpeg 003.png
... and so on ...

Es un gran truco cuando lo aprendes por primera vez, y al principio es una gran mejora. No hay necesidad de una GUI y clics constantes. Pero aún requiere mucha mano de obra.

Mejor aún:

$ for i in *jpeg; do convert $i $i.png ; done

Esto, al menos, pone en marcha el(los) trabajo(s) y lo libera para hacer cosas más productivas. El problema es que sigue siendo un proceso en serie. Una imagen se convierte, y luego la siguiente en la cola avanza para la conversión, y así sucesivamente hasta que la cola se haya vaciado.

Con Paralelo:

$ find . -name "*jpeg" | parallel -I% --max-args 1 convert % %.png

Esta es una combinación de dos comandos:find comando, que reúne los objetos en los que desea operar, y el parallel comando, que ordena los objetos y se asegura de que todo se procese según sea necesario.

  • find . -name "*jpeg" encuentra todos los archivos en el directorio actual que terminan en jpeg .
  • parallel invoca GNU paralelo.
  • -I% crea un marcador de posición, llamado % , para sustituir lo que sea find entrega a Parallel. Usas esto porque de lo contrario tendrías que escribir manualmente un nuevo comando para cada resultado de find , y eso es exactamente lo que intenta evitar.
  • --max-args 1 limita la velocidad a la que Parallel solicita un nuevo objeto de la cola. Dado que el comando Parallel se está ejecutando solo requiere un archivo, limita la tasa a 1. ¿Estaba ejecutando un comando más complejo que requería dos archivos (como cat 001.txt 002.txt > new.txt ), limitaría la tasa a 2.
  • convert % %.png es el comando que desea ejecutar en paralelo.

El resultado de este comando es que find reúne todos los archivos relevantes y los entrega a parallel , que inicia un trabajo e inmediatamente solicita el siguiente en línea. Parallel continúa haciendo esto mientras sea seguro iniciar nuevos trabajos sin paralizar su computadora. A medida que se completan los trabajos antiguos, los reemplaza por otros nuevos, hasta que se procesan todos los datos que se le proporcionan. Lo que tomaba 10 minutos antes podría tomar solo 5 o 3 con Parallel.

Múltiples entradas

El find El comando es una excelente puerta de entrada a Parallel siempre que esté familiarizado con find y xargs (colectivamente llamados GNU Find Utilities, o findutils ). Proporciona una interfaz flexible con la que muchos usuarios de Linux ya se sienten cómodos y es bastante fácil de aprender si es un principiante.

El find El comando es bastante sencillo:proporciona find con una ruta a un directorio que desea buscar y una parte del nombre del archivo que desea buscar. Utilice caracteres comodín para ampliar su red; en este ejemplo, el asterisco indica cualquier cosa , entonces find localiza todos los archivos que terminan con la cadena searchterm :

$ find /path/to/directory -name "*searchterm"

Por defecto, find devuelve los resultados de su búsqueda de un elemento a la vez, con un elemento por línea:

$ find ~/graphics -name "*jpg"
/home/seth/graphics/001.jpg
/home/seth/graphics/cat.jpg
/home/seth/graphics/penguin.jpg
/home/seth/graphics/IMG_0135.jpg

Cuando canaliza los resultados de find a parallel , cada elemento de cada línea se trata como un argumento del comando que parallel está arbitrando. Si, por otro lado, necesita procesar más de un argumento en un comando, puede dividir la forma en que los datos en la cola se entregan a parallel .

Aquí hay un ejemplo simple y poco realista, que luego convertiré en algo más útil. Puede seguir este ejemplo, siempre que tenga instalado GNU Parallel.

Suponga que tiene cuatro archivos. Enumérelos, uno por línea, para ver exactamente lo que tiene:

$ echo ada > ada ; echo lovelace > lovelace
$ echo richard > richard ; echo stallman > stallman
$ ls -1
ada
lovelace
richard
stallman

Desea combinar dos archivos en un tercero que contenga el contenido de ambos archivos. Esto requiere que Parallel tenga acceso a dos archivos, por lo que -I% variable no funcionará en este caso.

El comportamiento predeterminado de Parallel es básicamente invisible:

$ ls -1 | parallel echo
ada
lovelace
richard
stallman

Ahora dígale a Parallel que desea obtener dos objetos por trabajo:

$ ls -1 | parallel --max-args=2 echo
ada lovelace
richard stallman

Ahora las líneas se han combinado. Específicamente, dos resultados de ls -1 se pasan a Parallel todos a la vez. Esa es la cantidad correcta de argumentos para esta tarea, pero en realidad son un solo argumento en este momento:"ada lovelace" y "richard stallman". Lo que realmente quiere son dos argumentos distintos por trabajo.

Afortunadamente, ese tecnicismo es analizado por Parallel mismo. Si establece --max-args a 2 , obtienes dos variables, {1} y {2} , que representa la primera y la segunda parte del argumento:

$ ls -1 | parallel --max-args=2 cat {1} {2} ">" {1}_{2}.person

En este comando, la variable {1} es ada o richard (según el trabajo que busques) y {2} es lovelace o stallman . El contenido de los archivos se redirige con un símbolo de redirección entre comillas (las comillas toman el símbolo de redirección de Bash para que Parallel pueda usarlo) y se colocan en nuevos archivos llamados ada_lovelace.person y richard_stallman.person .

$ ls -1
ada
ada_lovelace.person
lovelace
richard
richard_stallman.person
stallman

$ cat ada_*person
ada lovelace
$ cat ri*person
richard stallman

Si pasa todo el día analizando archivos de registro que tienen un tamaño de cientos de megabytes, es posible que vea cómo el análisis de texto paralelizado podría serle útil; de lo contrario, esto es principalmente un ejercicio demostrativo.

Sin embargo, este tipo de procesamiento es invaluable para algo más que el análisis de texto. He aquí un ejemplo de la vida real del mundo del cine. Considere un directorio de archivos de video y archivos de audio que deben unirse.

$ ls -1
12_LS_establishing-manor.avi
12_wildsound.flac
14_butler-dialogue-mixed.flac
14_MS_butler.avi
...and so on...

Usando los mismos principios, se puede crear un comando simple para que los archivos se combinen en paralelo :

$ ls -1 | parallel --max-args=2 ffmpeg -i {1} -i {2} -vcodec copy -acodec copy {1}.mkv

Bruto. Fuerza.

Todo este sofisticado análisis de entrada y salida no es del gusto de todos. Si prefiere un enfoque más directo, puede lanzar comandos a Parallel y alejarse.

Primero, cree un archivo de texto con un comando en cada línea:

$ cat jobs2run
bzip2 oldstuff.tar
oggenc music.flac
opusenc ambiance.wav
convert bigfile.tiff small.jpeg
ffmepg -i foo.avi -v:b 12000k foo.mp4
xsltproc --output build/tmp.fo style/dm.xsl src/tmp.xml
bzip2 archive.tar

Luego entregue el archivo a Parallel:

$ parallel --jobs 6 < jobs2run

Y ahora todos los trabajos en su archivo se ejecutan en paralelo. Si existen más trabajos de los permitidos, Parallel forma y mantiene una cola hasta que se hayan ejecutado todos los trabajos.

Mucho, mucho más

GNU Parallel es una herramienta potente y flexible, con muchos más casos de uso de los que caben en este artículo. Su página de manual proporciona ejemplos de cosas realmente geniales que puede hacer con él, desde la ejecución remota a través de SSH hasta la incorporación de funciones Bash en sus comandos paralelos. Incluso hay una extensa serie de demostraciones en YouTube, para que pueda aprender directamente del equipo de GNU Parallel. El mantenedor principal de GNU Parallel también acaba de publicar la guía oficial del comando, disponible en Lulu.com.

GNU Parallel tiene el poder de cambiar la forma en que computa, y si no lo hace, al menos cambiará el tiempo que su computadora dedica a la computación. ¡Pruébalo hoy!


Linux
  1. Encuentra archivos y directorios en Linux con el comando de búsqueda

  2. 8 consejos para la línea de comandos de Linux

  3. Trabajando con tuberías en la línea de comando de Linux

  4. ¿Cómo obtengo la cantidad de cuadros en un video en la línea de comando de Linux?

  5. Monitoreo del nivel del micrófono con una herramienta de línea de comandos en Linux

'Getting to Done' en la línea de comandos de Linux

Cómo revisar la ortografía en la línea de comandos de Linux con Aspell

Cómo encontrar archivos en Linux con el comando Buscar

Domina la línea de comandos de Linux

Cómo buscar archivos desde la línea de comandos de Linux

Cómo encontrar archivos con el comando fd en Linux