Séquentiel: for i in {1..1000}; do do_something $i; done
- trop lent
Parallèle: for i in {1..1000}; do do_something $i& done
- trop de charge
Comment exécuter des commandes en parallèle, mais pas plus de, par exemple, 20 instances par moment?
Maintenant, en utilisant généralement hack like for i in {1..1000}; do do_something $i& sleep 5; done
, mais ce n'est pas une bonne solution.
Mise à jour 2 : conversion de la réponse acceptée en script: http://vi-server.org/vi/parallel
#!/bin/bash
NUM=$1; shift
if [ -z "$NUM" ]; then
echo "Usage: parallel <number_of_tasks> command"
echo " Sets environment variable i from 1 to number_of_tasks"
echo " Defaults to 20 processes at a time, use like \"MAKEOPTS='-j5' parallel ...\" to override."
echo "Example: parallel 100 'echo \$i; sleep \`echo \$RANDOM/6553 | bc -l\`'"
exit 1
fi
export CMD="$@";
true ${MAKEOPTS:="-j20"}
cat << EOF | make -f - -s $MAKEOPTS
PHONY=jobs
jobs=\$(shell echo {1..$NUM})
all: \${jobs}
\${jobs}:
i=\$@ sh -c "\$\$CMD"
EOF
Notez que vous devez remplacer 8 espaces par 2 tabulations avant "i =" pour que cela fonctionne.
parallel
in moreutils n'est pas GNU Parallel et est assez limité dans ses options. La commande ci-dessus ne fonctionnera pas avec le parallèle de moreutils.xargs --max-procs=20
.Ce n'est pas une solution bash, mais vous devez utiliser un Makefile, éventuellement
-l
pour ne pas dépasser une charge maximale.Ensuite, pour démarrer 20 emplois à la fois,
ou pour démarrer autant de travaux que possible sans dépasser une charge de 5
la source
echo -e 'PHONY=jobs\njobs=$(shell echo {1..100000})\n\nall: ${jobs}\n\n${jobs}:\n\t\techo $@; sleep `echo $$RANDOM/6553 | bc -l`' | make -f - -j20
Maintenant, il semble encore plus hacky.publier le script dans la question avec mise en forme:
Notez que vous devez remplacer 8 espaces par 2 tabulations avant "i =".
la source
Une idée simple:
Recherchez i modulo 20 et exécutez la commande shell d'attente avant do_something.
la source
Vous pouvez utiliser
ps
pour compter le nombre de processus en cours d'exécution et chaque fois que cela tombe en dessous d'un certain seuil, vous démarrez un autre processus.Pseudo code:
la source
la source
while [ `jobs | wc -l` -ge 20]; do
?njobs
deux fois, et les performances sont assez importantes dans les scripts shell qui exécutent des tâches de veille;)sleep 1
àsleep 0.1
et cela commence à faire en moyenne njobs à 40-50 au lieu de 20. S'il y a plus de 20 emplois, nous devons attendre que tout travail soit terminé, pas seulement attendre 1 seconde.vous pouvez le faire comme ça.
utilisant des tubes nommés, à chaque fois, il exécute 20 sous-shell en parallèle.
J'espère que cela vous aidera :)
la source