processes parallel multiple bash parallel-processing

bash - multiple - parallel execution linux



Fácil paralelización (8)

A menudo me encuentro escribiendo simples loops para realizar una operación en muchos archivos, por ejemplo:

for i in `find . | grep ".xml$"`; do bzip2 $i; done

Parece un poco deprimente que en mi máquina de 4 núcleos solo se esté usando un núcleo ... ¿hay alguna manera fácil de agregar paralelismo a mis scripts de shell?

EDITAR: Para introducir un poco más de contexto a mis problemas, lo siento, no estaba más claro para empezar!

A menudo quiero ejecutar scripts simples (ish), como trazar un gráfico, comprimir o descomprimir, o ejecutar algún programa, en conjuntos de datos de tamaño razonable (generalmente entre 100 y 10.000). Los scripts que uso para resolver estos problemas se parecen al anterior, pero pueden tener un comando diferente, o incluso una secuencia de comandos para ejecutar.

Por ejemplo, justo ahora estoy corriendo:

for i in `find . | grep ".xml.bz2$"`; do find_graph -build_graph $i.graph $i; done

¡Entonces mis problemas no son bzip específicos! (Aunque el bzip paralelo se ve bien, tengo la intención de usarlo en el futuro).


Creo que podrías hacer lo siguiente

for i in `find . | grep ".xml$"`; do bzip2 $i&; done

Pero eso generaría tantos procesos como archivos al instante y no es óptimo, ya que solo ejecuta cuatro procesos a la vez.


Encuentro este tipo de operación contraproducente. La razón es que cuantos más procesos acceden al disco al mismo tiempo, mayor es el tiempo de lectura / escritura, por lo que el resultado final termina en un tiempo más prolongado. El cuello de botella aquí no será un problema de CPU, no importa cuántos núcleos tenga.

¿Nunca ha realizado una simple copia de dos archivos grandes al mismo tiempo en la misma unidad de HD? Por lo general, soy más rápido para copiar uno y luego otro.

Sé que esta tarea implica un poco de potencia de CPU (bzip2 es un método de compresión exigente), pero intente medir la carga de la primera CPU antes de seguir el camino "desafiante" que todos los técnicos tendemos a elegir mucho más a menudo de lo necesario.


Hice algo como esto por bash. El truco de hacer paralelos es probablemente mucho más rápido para los one-offs, pero aquí está la sección del código principal para implementar algo como esto en bash, aunque tendrás que modificarlo para tus propósitos:

#!/bin/bash # Replace NNN with the number of loops you want to run through # and CMD with the command you want to parallel-ize. set -m nodes=`grep processor /proc/cpuinfo | wc -l` job=($(yes 0 | head -n $nodes | tr ''/n'' '' '')) isin() { local v=$1 shift 1 while (( $# > 0 )) do if [ $v = $1 ]; then return 0; fi shift 1 done return 1 } dowait() { while true do nj=( $(jobs -p) ) if (( ${#nj[@]} < nodes )) then for (( o=0; o<nodes; o++ )) do if ! isin ${job[$o]} ${nj[*]}; then let job[o]=0; fi done return; fi sleep 1 done } let x=0 while (( x < NNN )) do for (( o=0; o<nodes; o++ )) do if (( job[o] == 0 )); then break; fi done if (( o == nodes )); then dowait; continue; fi CMD & let job[o]=$! let x++ done wait


La respuesta a la pregunta general es difícil, porque depende de los detalles de las cosas que está paralelizando. Por otro lado, para este propósito específico, debe usar pbzip2 en lugar de simple bzip2 (es probable que pbzip2 ya esté instalado o al menos en los repositorios o su distribución). Vea aquí para más detalles: http://compression.ca/pbzip2/


gnu make tiene una buena característica de paralelismo (por ejemplo, -j 5) que funcionaría en su caso. Crear un Makefile

%.xml.bz2 : %.xml all: $(patsubt %.xml,%xml.bz2,$(shell find . -name ''*.xml'') )

entonces haz una

nice make -j 5

reemplace ''5'' con un número, probablemente 1 más que la cantidad de CPU. Es posible que desee hacer ''bueno'' esto en caso de que alguien más quiera usar la máquina mientras está en ella.


Este programa perl se adapta bastante bien a sus necesidades, simplemente haría esto:

runN -n 4 bzip2 `find . | grep ".xml$"`


Solución : use xargs para ejecutar en paralelo (¡no olvide la opción -n !)

find -name /*.xml -print0 | xargs -0 -n 1 -P 3 bzip2


Si tuviera que resolver el problema hoy probablemente usaría una herramienta como GNU Parallel (a menos que haya una herramienta paralelizada especializada para su tarea como pbzip2 ):

find . | grep ".xml$" | parallel bzip2

Aprender más: