Multithreading : script bash.
Il y a plusieurs mois (si ce n’est pas un an), j’ai lu le billet d’un blog aujourd’hui fermé qui présentait une idée pour rendre un script utilisation la parallélisation. Avec les processeurs multi-coeur, je pense que l’on devrait plus fréquemment utiliser ce procédé. Pour l’anecdote, cela m’a bien été utile lorsque j’ai utilisé une machine ayant 8 coeurs lors d’un stage
Ce billet n’est pas une simple recopie du billet que j’ai pu lire puisque le script possédait un petit bug. Je vais donc le corriger ici.
On va dire que une action élémentaire traite un fichier, et que l’ensemble des fichiers est passé en argument du script.
current=1
numthreads=`cat /proc/cpuinfo|grep ‘^processor’|wc -l`
while [ $# -gt 0 ]
do
action $1 &
div=$((current/$numthreads))
mul=$((div*$numthreads))
# wait if numthreads jobs are running
if [ "$mul" = "$current" ]
then
#we reached the max of thread number
wait
else
#we wait if this thread is the last one
[[ $# -eq 1 ]] && wait
fi
current=$((current+1))
#shift to the next file
shift
done
Je vais commenter rapidement la méthode. On définie une variable current pour le numéro du thread, on récupère dans numthreads le nombre de coeurs du procésseur. Tant qu’il reste des arguments au script (à chaque étape on supprime l’argument traité) on va exécuter la fonction action quu n’est pas définie ici. Les deux lignes suivantes vérifient si deux on a lancé numthreads tâches ou non. Si c’est le cas, on attend la fin de toutes les actions précédemment lancées. Si l’argument traité s’avère être le dernier de la liste, on attend aussi l’ensemble des tâches lancées. (et c’est ce point qui avait été oublié ; le script était quitté alors qu’un thread tournait encore.)
L’inconvénient (il faut en être conscient) de ce script est que les actions élémentaires doivent avoir typiquement le même temps d’exécution sans quoi on ne sera pas très efficace car une tâche longue va occupé un coeur alors que les autres seront libres.