J'ai un script shell qui
Donc, le pseudocode ressemble à ceci
file1.sh
#!/bin/bash
for i in $(seq 1 1000)
do
Generating random numbers here , sorting and outputting to file$i.txt
done
Existe-t-il un moyen d'exécuter ce script Shell dans parallel
pour exploiter pleinement les processeurs multicœurs?
Pour le moment, ./file1.sh
s'exécute en séquence de 1 à 1000 exécutions et il est très lent.
Merci de votre aide.
Vérifiez bash subshells , ils peuvent être utilisés pour exécuter des parties d’un script en parallèle.
Je n'ai pas testé cela, mais cela pourrait être un début:
#!/bin/bash
for i in $(seq 1 1000)
do
( Generating random numbers here , sorting and outputting to file$i.txt ) &
if (( $i % 10 == 0 )); then wait; fi # Limit to 10 concurrent subshells.
done
wait
Une autre façon très pratique de faire cela est avec gnu parallel , qui vaut bien une installation si vous ne l'avez pas déjà. c'est inestimable si les tâches ne prennent pas nécessairement la même quantité de temps.
seq 1000 | parallel -j 8 --workdir $PWD ./myrun {}
va lancer ./myrun 1
, ./myrun 2
, etc., en s'assurant que 8 tâches à la fois sont en cours d'exécution. Il peut également prendre des listes de nœuds si vous souhaitez exécuter plusieurs nœuds à la fois, par exemple dans un travail PBS; Nos instructions à nos utilisateurs pour savoir comment procéder sur notre système sont ici .
Mis à jour pour ajouter: Vous voulez vous assurer que vous utilisez gnu-parallel, pas l'utilitaire plus limité du même nom qui est inclus dans le paquetage moreutils (l'histoire divergente des deux est décrite ici .)
Pour que les choses fonctionnent en parallèle, utilisez '&' à la fin d'une commande Shell pour l'exécuter en arrière-plan. wait
attendra par défaut (c'est-à-dire sans arguments) que tous les processus en arrière-plan soient terminés. Alors, lancez peut-être 10 en parallèle, puis attendez, puis faites-en dix de plus. Vous pouvez le faire facilement avec deux boucles imbriquées.
Il existe une liste complète de programmes pouvant exécuter des tâches en parallèle à partir d'un shell, qui inclut même des comparaisons entre eux, dans la documentation de GNU parallèle. Il existe de très nombreuses solutions. Une autre bonne nouvelle est qu’ils sont probablement assez efficaces pour la planification des travaux, de sorte que tous les cœurs/processeurs restent occupés en permanence.
Il existe un programme simple et portable qui fait cela pour vous: PPSS . PPSS planifie automatiquement les travaux pour vous, en vérifiant le nombre de cœurs disponibles et en lançant un autre à chaque fois.
IDLE_CPU=1
NCPU=$(nproc)
int_childs() {
trap - INT
while IFS=$'\n' read -r pid; do
kill -s SIGINT -$pid
done < <(jobs -p -r)
kill -s SIGINT -$$
}
# cmds is array that hold commands
# the complex thing is display which will handle all cmd output
# and serialized it correctly
trap int_childs INT
{
exec 2>&1
set -m
if [ $NCPU -gt $IDLE_CPU ]; then
for cmd in "${cmds[@]}"; do
$cmd &
while [ $(jobs -pr |wc -l) -ge $((NCPU - IDLE_CPU)) ]; do
wait -n
done
done
wait
else
for cmd in "${cmds[@]}"; do
$cmd
done
fi
} | display