Quiero procesar muchos archivos y desde que tengo aquí un montón de núcleos, quiero hacerlo en paralelo:
for i in *.myfiles; do do_something $i `derived_params $i` other_params; done
Sé de una solución Makefile pero mis comandos necesitan los argumentos de la lista global de shell. Lo que encontré es:
> function pwait() {
> while [ $(jobs -p | wc -l) -ge $1 ]; do
> sleep 1
> done
> }
>
Para usarlo, todo lo que hay que hacer es poner y después de los trabajos y una llamada en espera, el parámetro proporciona la cantidad de procesos paralelos:
> for i in *; do
> do_something $i &
> pwait 10
> done
Pero esto no funciona muy bien, por ejemplo, lo probé con, por ejemplo, un bucle for que convierte muchos archivos, pero me dio un error y dejó los trabajos sin hacer.
No puedo creer que esto aún no se haya hecho ya que la discusión sobre la lista de correo de zsh es muy antigua por ahora. Entonces, ¿sabes algo mejor?
bash
shell
zsh
parallel-processing
matemáticas
fuente
fuente
echo "DONE"
después del ciclo que se ejecutó antes de que los trabajos activos no finalicen. => Esto me hizo pensar que los trabajos no estaban hechos.Respuestas:
Un archivo MAKE es una buena solución a su problema. Podrías programar esta ejecución paralela en un shell, pero es difícil, como has notado. Una implementación paralela de make no solo se encargará de iniciar trabajos y detectar su finalización, sino que también se encargará del equilibrio de carga, lo cual es complicado.
El requisito de globbing no es un obstáculo: hay implementaciones de make que lo soportan. GNU make, que tiene expansión de comodines como
$(wildcard *.c)
y acceso de shell como$(shell mycommand)
(funciones de búsqueda en el manual de GNU make para obtener más información). Es el valor predeterminadomake
en Linux y está disponible en la mayoría de los otros sistemas. Aquí hay un esqueleto de Makefile que puede adaptar a sus necesidades:Ejecute algo como
make -j4
ejecutar cuatro trabajos en paralelo omake -j -l3
mantener el promedio de carga alrededor de 3.fuente
No estoy seguro de cómo son sus argumentos derivados. Pero con GNU Parallel http: // www.gnu.org/software/parallel/ puede hacer esto para ejecutar un trabajo por núcleo de CPU:
Si lo que desea obtener es simplemente cambiar la extensión. {.} Puede ser útil:
Mire el video de introducción a GNU Parallel en http://www.youtube.com/watch?v=OpaiGYxkSuQ
fuente
¿No usaría el
wait
comando del shell para usted?Su ciclo ejecuta un trabajo, luego lo espera y luego realiza el siguiente trabajo. Si lo anterior no funciona para usted, entonces el suyo podría funcionar mejor si se muda
pwait
despuésdone
.fuente
for
bucles anidados para limitar eso:for file in *; do for i in {1..10}; do do_something "$i" & done; wait; done
(no probado) Eso debería hacer diez a la vez y esperar hasta que se terminen los diez de cada grupo antes de comenzar los siguientes diez. Su ciclo hace uno a la vez haciendo la&
discusión. Vea la pregunta que JRobert enlazó para otras opciones. Busque en Stack Overflow otras preguntas similares a las suyas (y esa).for i in *
. Tendría que pasar argumentos al bucle con una tubería o algo así. Luego, en lugar de un bucle interno, puede ejecutar un contador incremental y ejecutar"micro-"wait"-s"
cada "$ ((i% 32))" -eq '0'wait
con un contador interno funcionó bien para mí. ¡Gracias!¿Por qué nadie ha mencionado xargs todavía?
Asumiendo que tienes exactamente tres argumentos,
De lo contrario, use un delimitador (nulo es útil para eso):
EDITAR: para lo anterior, cada parámetro debe estar separado por un carácter nulo, y luego el número de parámetros debe especificarse con xargs -n.
fuente
Intenté algunas de las respuestas. Hacen que el script sea un poco más complejo de lo que se necesita. Lo ideal sería utilizar
parallel
oxargs
sería preferible, sin embargo, si las operaciones dentro del ciclo for son complicadas, podría ser problemático crear archivos de líneas grandes y largas para suministrar en paralelo. en su lugar podríamos usar la fuente de la siguiente maneraPor lo tanto, para su problema, la solución se vería así
definir hacer algo como
do_something.sh
}
ejecutar con
xarg
ognu parallel
Supongo que la independencia funcional de las iteraciones de for está implícita.
fuente